home *** CD-ROM | disk | FTP | other *** search
/ TOS Silver 2000 / TOS Silver 2000.iso / programm / Mm2_txt / MODULA5F.TXT < prev    next >
Encoding:
Text File  |  1997-02-08  |  165.7 KB  |  3,154 lines

  1. 5.1 Bibliothek: Allgemeines                                                5 -   1
  2. ________________________________________________________
  3.  
  4.  
  5. 5.1  Allgemeines  zur  Bibliothek
  6.  
  7.  
  8. Funktionsübersicht
  9.  
  10. Bevor  Sie  weiterblättern  und  womöglich  von  der  Funktionsvielfalt  der  über
  11. einhundert Module erschlagen werden, geben wir Ihnen eine kleine Übersicht.
  12.  
  13. Einige Module kennen Sie sicher schon aus Ihrem Modula-2 Buch:
  14.  
  15.    - InOut      zur Ein-/Ausgabe über Tastatur und Bildschirm,
  16.    - Terminal   ebenso (aber nur auf TOS-Bildschirm ohne GEM!)
  17.    - Mathlib0   mit mathematischen Funktionen für REALs/LONGREALs,
  18.    - Strings    zum Arbeiten mit Zeichenketten und
  19.    - Storage   um NEW und DISPOSE verwenden zu können.
  20.  
  21. Wenn Sie Neueinsteiger in Modula-2 sind, reicht es aus, wenn Sie sich erst
  22. einmal nur mit diesen Modulen beschäftigen.
  23.  
  24. Für Fortgeschrittene folgt eine Übersicht weiterer nützlicher Module:
  25.  
  26. Dateifunktionen:
  27.     Files, Text, NumberIO, Binary, Directory.
  28.  
  29. Grafik (GEM)
  30.     AES...,   VDI...,    GEM...,    ObjHandler,    EventHandler,    TextWindows,
  31.     WindowBase, WindowLists, EasyGEM0, EasyGEM1.
  32.  
  33. String/Zahlen-Umwandlung:
  34.     Convert, StrConv, Strings, FuncStrings.
  35.  
  36. Tastatur- und Zeichenauswertung:
  37.     Characters, Keyboard.
  38.  
  39. Programmkontrolle:
  40.     Loader, ModCtrl, PrgCtrl.
  41.  
  42. Diverse Hilfsfunktionen
  43.     SysUtil0      - Variablenvergleiche, -löschen, -lopieren, Bit-Funktionen
  44.     SysUtil1       - Speicherzugriffe aller Art, auch im Supervisormodus
  45.     SysUtil2      - SetJump/LongJump (wie in C), Supervisormodus
  46.     Clock         - Datums-/Zeitbestimmung
  47.     TimeConvert  - Datums-/Zeit-Ein- und Ausgabe
  48.     Lists          - Verwaltung allgemeiner Listen
  49.     RandomGen   - Zufallszahlenerzeugung
  50.  
  51. Alle Module sind jeweils in ihren Definitionstexten (s. Anhang) dokumentiert!
  52. 5.1 Bibliothek: Allgemeines                                                5 -  2
  53. ________________________________________________________
  54.  
  55.  
  56. Übersicht der vorhandenen Module
  57.  
  58. Folgende Megamax-Module stehen Ihnen incl. Quelltexten zur Verfügung
  59. (Ordner MOS):
  60.  
  61. GEMDebug    - Hilfsmodul zum schrittweisen Ausführen v. Modula-Programmen
  62. TOSDebug    - wie GEMDebug, aber mit TOS- statt Fensterausgabe
  63.  
  64. GEMError    - Treibermodul zum Abfangen v. Laufzeitfehlern (komfortabel)
  65. SimpleError  - Wie GEMError, nur einfacher (siehe Kapitel 2.6 über Linker)
  66. GEMScan     - Hilfsmodul zum Anzeigen v. Laufzeitfehlern
  67.  
  68. GEMIO       - Treibermodul zur Ausgabe von InOut in ein GEM-Window
  69. TOSIO        - Treibermodul zur Ausgabe von InOut über BIOS-Routinen
  70. GEMDOSIO   - Treibermodul zur Ausgabe von InOut über GEMDOS-Routinen
  71.  
  72. M2Init        - Initialisierungsmodul für alle gelinkten Programme
  73. MM2Shell     - Die Shell zum Selbstverändern
  74. MOSConfig   - Konfiguationsvariablen für Loader, ErrBase, InOut usw.
  75.  
  76. Von folgenden Modulen haben Sie die Codeversionen erhalten (Ordner IMP):
  77.  
  78. ArgCV        - Auswertung der Argumentzeile (Command-Line)
  79. ArgCVIO      - Auswertung der Argumentzeile mit E/A-Umleitungsmöglichkeit
  80. Binary        - Dateisystem: E/A für Binärdaten, Seek, FileSize
  81. BinOps        - Vergleichsfunktionen für jeweils zwei Werte
  82. BIOS         - BIOS-Funktionen
  83. Block         - Sehr schnelles Löschen und Kopieren großer Datenbereiche
  84. Calls          - Aufruf von Modula-fremden Routinen (z.B. Betriebssystem)
  85. Characters   - ASCII-Konstanten und Funktionen zum Auswerten von Zeichen
  86. Clock         - Zeit- und Datumsbestimmung
  87. Compressions- Datenkomprimierung
  88. Console       - Wie Terminal, jedoch Ausgabe über GEMDOS statt BIOS
  89. Convert       - Umwandlung Zahlen <-> Strings (siehe auch StrConv)
  90. Directory     - Löschen u. Umbenennen v. Dateien, Directory-Hilfsfunktionen
  91. EasyExceptions - Komfortables Abfangen von Laufzeitfehlern
  92. ErrBase      - Grundmodul zum Abfangen von allgemeinen Laufzeitfehlern
  93. Excepts       - Abfangen der Exceptions des Prozessors (680x0)
  94. FastStrings   - Alternatives Strings-Modul
  95. FileBase      - Dateisystem: Fehlerbehandlung und Device-Treiber
  96. FileNames    - Zusammensetzen und Analysieren von Datei- und Pfadnamen
  97. Files          - Dateisystem: Öffnen und Schließen v. Dateien
  98. FPUSupport   - Für Benutzung der FPU in Accessories und Coroutinen
  99. FuncStrings   - Komfortablere String-Funktionen (Pascal-ähnlich)
  100. GEMDOS     - GEMDOS-Funktionen
  101. HdlError      - Spezielles Modul zum Abfangen von allg. Laufzeitfehlern
  102. InOut         - Standard Ein- und Ausgabe
  103. InOutBase    - Modul für InOut-Treiber (z.B. GEMIO, TOSIO, GEMDOSIO)
  104. 5.1 Bibliothek: Allgemeines                                                5 -  3
  105. ________________________________________________________
  106.  
  107.  
  108. KbdCtrl       - Direkte Tastaturabfrage/-kontrolle
  109. Keyboard     - Auswertung von Tasten mit sog. Scan-Codes
  110. LibFiles       - Verwaltung von Library-Dateien
  111. Lists          - Verwaltung doppelt verketteter Listen
  112. Loader        - Ausführen von Programmen, auch mit Load-Time-Linking
  113. MathLib0     - Mathematische Grundfunktionen f. REAL-Zahlen
  114. ModCtrl       - Modulverwaltung, Prozeduren als Prozeß starten
  115. MOSGlobals  - System-globale Konstanten und TYPE-Definitionen
  116. NumberIO    - Dateisystem: E/A von Zahlen in Textform
  117. Paths         - Dateien-Suchfunktionen
  118. PathEnv       - Directory-Umgebung: HomePath und File-Selector
  119. PathCtrl      - Verwaltung von Pfadliste f. Paths-Modul
  120. PrgCtrl       - Programm-/Prozeßkontrolle (siehe auch ResCtrl)
  121. RandomGen   - Zufallszahlenbestimmung
  122. ResCtrl       - Modulkontrolle (siehe auch PrgCtrl)
  123. ResourceHandler - komfortable Prozeßkontrolle (setzt auf PrgCtrl, ResCtrl auf)
  124. Runtime       - Laufzeitfunktionen, automatisch vom Compiler importiert
  125. Storage       - Speicherverwaltung
  126. StorBase     - Systemnahes Modul zur Speicherverwaltung
  127. StrConv      - Erweiterte Zahlenumwandlungsfunktionen zu Convert
  128. StringEditor  - Allg. Funktion zur komfortablen Eingabe einer Textzeile.
  129. Strings       - String-Funktionen (siehe auch FastStrings, FuncStrings)
  130. SysCtrl       - Hilfsroutinen für den Scanner (Module GEMError, GEMScan)
  131. SysInfo       - Ermittelt Prozessortype, Koprozessor, TOS-Version
  132. SysTypes     - Definition v. Systemtypen
  133. SysUtil0      - Hilfsfunktionen zum Löschen v. Variablen, Vergleichen usw.
  134. SysUtil1       - Speicherzugriffe aller Art, auch im Supervisormodus
  135. SysUtil2      - SetJump/LongJump (wie in C), Super-Funktion
  136. SysVars      - Systemvariablen des TOS
  137. TermBase    - Treibermodul zu Terminal
  138. Terminal      - InOut-Treiber f. TOS-Bildschirm (BIOS-Ein-/Ausgaben)
  139. Text          - Dateisystem: E/A von Textdaten
  140.                                            < >
  141. TimeConvert  - Umwandlung Zeit/Datum  -  Text (s. Clock)
  142. UserBreak    - Ermöglicht Abbrechen von Programmen über Tastatur
  143. UserTrace    - Alternative zu Debug
  144. VT52         - Escape-Sequenzen des VT-52-Emulators (f. Textausgaben)
  145. XBIOS        - XBIOS-Funktionen
  146. XBRA         - Bequeme XBRA-Installation
  147. 5.1 Bibliothek: Allgemeines                                                5 -  4
  148. ________________________________________________________
  149.  
  150.  
  151. AES...        - AES-Funktionen des GEM
  152. VDI...         - VDI-Funktionen des GEM
  153. EasyGEM0    - Allgemeine GEM-Hilfsfunktionen
  154. EasyGEM1    - Bequemer Aufruf des Datei-Selektors und der Clipboard-Funk~
  155.                  tionen (Klemmbrett, Scrap-Directory)
  156. EventHandler - Zentrale Verwaltung aller Events des GEM für das MOS
  157. FastGEM0    - Teils optimierte VDI-Funktionen
  158. FileManagement - Shell-Funktionen: Kopieren, Löschen usw.
  159. GEMEnv      - Verwaltung der GEM-Umgebung
  160. GEMGlobals   - Definitionen globaler GEM-Strukturen
  161. GrafBase     - Grafische Hilfsfunktionen
  162. KbdEvent     - Synchronisiert Tastenereignisse mit Sondertasten (Shift usw.)
  163. LineA         - Line A-Funktionen des TOS.
  164. ObjHandler    - Komfortabler Zugriff auf GEM-Objektbäume
  165. TextWindows - Komfortable Fensterverwaltung für Textausgaben
  166. WindowBase  - Allgemeines Fenster-Kontrollmodul
  167. WindowLists  - Verwaltet automatisch Textzeilen in einem Fenster
  168.  
  169. Die  folgenden  Module  sind  nicht  dokumentiert,  da  sie  nur  systemintern
  170. verwendet werden und Änderungen vorbehalten sind:
  171.  
  172. GEMShare    - GEM-Systemmodul
  173. InOutFile      - Hilfsmodul für InOut
  174. MOSCtrl      - Grundmodul für alle Programme
  175. ModBase      - Hilfsmodul für Loader & ModBase
  176. SFP004       - Verwaltung f. evtl. vorhandenen Mathe-Koprozessor (68881)
  177. SystemError  - Programmabbruch bei fatalen Fehlern (Speichermangel usw)
  178.  
  179. Module, die nicht zum MOS gehören und jederzeit von uns oder Ihnen geändert
  180. werden können:
  181.  
  182. MM2ShellRsc - GEM-Resource-Konstanten, mit NRSC  ASH.PRG zu erzeugen.
  183.                                                          _
  184.                  Wollen Sie die Shell erweitern, dürfen Sie natürlich dabei auch
  185.                  eine neue Resource-Datei erzeugen und verwenden, denn sie
  186.                  wird nur  von  der  Shell  importiert,  auf  deren  Quelltext  Sie
  187.                  ebenfalls Zugriff haben.
  188. ShellMsg      - Hilfsmodul zur Kommunikation zw. Shell, Compiler und Linker.
  189.                  Achtung - greifen Sie nicht in Ihren normalen Anwendungen
  190.                  darauf zu! Erstens  sind  die  Werte  in  gelinkten  Programme
  191.                  nicht  mehr  initialisiert  (weil  das  nur  die  Modula-Shell  tut),
  192.                  zweitens  behalten  wir  uns  jederzeit  Änderungen  daran  vor,
  193.                  so  daß  Sie  dann  Versionskonflikte  oder  andere  Probleme
  194.                  bekommen.
  195. 5.1 Bibliothek: Allgemeines                                                5 -  5
  196. ________________________________________________________
  197.  
  198.  
  199. Beispielprogramme (im DEMO-Ordner - Dokumentation in den Quelltexten)
  200.  
  201. AccDemo     - einfache Accessory-Demo
  202. AsmDemo    - Beispiele für Aufruf der TOS-Funktionen in Assembler
  203. Dhrystone    - Verbreitetes Testprogramm für Compiler-Qualität (Codeerz.)
  204. ExcDemo     - Demonstriert Anwendung des Moduls Excepts
  205. ExcTest      - Demonstriert Anwendung des Moduls Exceptions
  206. Hatschi       - Demonstration von Coroutinen, auch als Interrupts
  207. InitPath       - Hilfsmodul zum Initialisieren einer Pfadliste f. Paths-Funktionen
  208. KbdTest      - Residentes Programm f. Tastaturmakros (KbdCtrl, ModCtrl)
  209. LocalModules - Zeigt die möglichen Import-/Export-Verhältnisse
  210. Sieve         - Auch ein Testprogramm für Compiler-Qualität (Codeerzeugung)
  211. TextDemo    - Demoprogramm für die VDI-Textausgabe
  212. Tiefe          - Sind/waren Sie auch ein MAD-Fan?
  213. WdwLists     - Zeigt Anwendung von WindowLists
  214.  
  215.  
  216. Hilfsprogramme (im UTILITY-Ordner - Dokumentation in den Quelltexten)
  217.  
  218. CompInit      - Ermöglicht es, den Compiler als gelinktes Programm zu starten,
  219.                  z.B. vom GEM-Desktop aus, um mehr Speicher frei zu haben.
  220. CmpFiles      - Kann mehrere Dateien in zwei Verzeichnissen vergleichen
  221. Decode       - Dekodiert Dateien
  222. DelFiles       - Löscht mehrere Dateien auf einmal
  223. DoSysInfo    - Zeigt Systeminformationen an (TOS-Version, Scrap-Dir usw.)
  224. Encode       - Kodiert (komprimiert) Dateien
  225. ExecMod      - Damit  kann  jedes  noch  ungelinkte  Programmodul  auch  vom
  226.                  Desktop gestartet werden
  227. GPA          - Ermittelt die Adresse von Prozeduren der Module im Speicher
  228. LibManager   - Anlegen und Bearbeiten von Library-Dateien
  229. LinkInit       - Ermöglicht es, den Linker als gelinktes Programm zu starten,
  230.                  z.B. vom GEM-Desktop aus, um mehr Speicher frei zu haben
  231. ModLoad      - Ein  nettes  Programm,  das  die  Mächtigkeit  von  Megamax
  232.                  Modula (speziell des Loaders) mal so richtig ausnutzt
  233. ModList       - Ähnlich Alternate-R in der Shell, aber ausführlicher
  234. ModTrace     - Residentes  Programm.  Zeigt  alle  Module  an,  die  durch
  235.                  Loadtime-Linking in der Shell geladen werden
  236. Monitor       - Erlaubt den Aufruf des Templemon beim Programmstart.
  237. PathEdit      - Prüfen und Ändern der Pfadlisten in der Shell
  238. SetTime      - Sorgt immer für korrekt  eingestellte  Zeit/Datum.  Unbedingt
  239.                  übersetzen, linken und in den AUTO-Ordner kopieren (s. auch
  240.                  Kapitel 2.7), wenn keine Uhr im Rechner vorhanden ist!
  241. ShowKeys    - "Quick-And-Dirty"-Programm,  das  alle  Tasteninformationen
  242.                  anzeigt (auch Scan-Codes), benutzt Keyboard & KbdCtrl.
  243. Time          - Anzeigen und Einstellen von Datum und Zeit
  244. Timer         - komplexere Accessory-Demo
  245. 5.1 Bibliothek: Allgemeines                                                5 -  6
  246. ________________________________________________________
  247.  
  248.  
  249. Allgemeine Hinweise zu den Modulen
  250.  
  251. Die Systemmodule, Programmkontrollmodule, Dateimodule sowie einige weitere
  252. Module bilden zusammen das "Modula Operating System", kurz MOS genannt.
  253.  
  254. Sys-Funktionen
  255.  
  256. In einigen Modulen finden sich Prozeduren, deren Namen mit Sys beginnen. Sie
  257. ergänzen immer ähnliche Prozeduren  ohne  diesen  Prefix.  Beispiel:  SysOpen
  258. neben Open und SysAlloc neben ALLOCATE. Wo immer dies auftritt, erzeugen
  259. die Prozeduren Resourcen (z.B. Dateien, Speicherbereiche), die normalerweise
  260. spätestens bei Beendigung des Programms (Prozeß) wieder freigegeben werden
  261. sollen. Damit  nichts  verloren  geht,  wenn  ein  Programm  nicht  selbst  dafür
  262. sorgt, bei Programmende alles wieder freizugeben bzw. zu schließen, wird dies
  263. automatisch von den Modulen des MOS durchgeführt. Nun gibt es Fälle, wo
  264. dies nicht erwünscht ist. Z.B. ist es möglich, über  globale  Variablen  eines
  265. anderen  Programms  (Prozeß)  Speicher  anzufordern,  der  beim  Enden  des
  266. Programms,  das  den  Speicher  anforderte,  nicht  automatisch  freigegeben
  267. werden soll. In diesem Fall wäre der Speicher mit SysAlloc statt ALLOCATE
  268. anzufordern. Die Sys... Funktionen sorgen also allgemein dafür, daß die damit
  269. angelegten  Resourcen  nicht  bei  Programmende  automatisch  freigegeben
  270. werden.  Sie  können  dann  nur  durch  den  expliziten  Aufruf  der  jeweils
  271. zugehörigen Freigabeprozedur freigegeben werden (z.B. Close, DEALLOCATE).
  272.  
  273. Wichtig ist die Anwendung solcher Sys-Funktionen vor allem bei Programmen,
  274. die resident bleiben (z.B. mit Hilfe der Funktion InstallModule aus ModCtrl) und
  275. bei Accessories. Bei Accessories sollten immer, wenn möglich, Sys-Funktionen
  276. verwendet werden, da es sonst aufgrund eines Konzeptionsfehlers vom TOS
  277. z.B.  passieren  kann,  daß  ein  im  ACC  angeforderter  Speicherbereich  bei
  278. Beendigung  eines  vom  Desktop  gestarteten  Programms  wieder  freigegeben
  279. wird, was dann zum Totalabsturz des Rechners führen kann.
  280.  
  281. Systemfunktionen
  282.  
  283. Es sind einige Funktionen in den Quelltexten als systemzugehörig oder intern
  284. ausgewiesen.  Solche  Funktionen  dürfen  in  keinem  Fall  von  Ihnen  ohne
  285. ausdrücklichen Hinweis von unserer Seite verwendet werden. Auch wenn Sie
  286. glauben, zu wissen, was die Funktionen im einzelnen tun - wir müssen Sie
  287. warnen, wir haben da schon böse Überraschungen erlebt! Teilweise behalten
  288. wir uns auch vor, diese Funktionen in späteren Versionen intern für andere
  289. Zwecke zu mißbrauchen.
  290. 5.1 Bibliothek: Allgemeines                                                5 -  7
  291. ________________________________________________________
  292.  
  293.  
  294. Übertragung (Portierung) von Modula-2 Programmen fremder Systeme
  295.  
  296. Wenn Sie Programme von anderen Modula-2 Systemen  übernehmen  wollen,
  297. können Programmänderungen notwendig werden. Zum einen ist es möglich, daß
  298. hardwarespezifische Zugriffe stattfinden. Hier mag eine Anpassung schwierig
  299. sein, und wir können Ihnen dabei leider nicht helfen. Dann kommt es vor, daß
  300. andere Modula-2 Compiler Datentypen in anderen Formaten verarbeiten und es
  301. dabei  z.B.  bei  Typanpassungen  zu  verschiedenen  Ergebnissen  kommt.  Das
  302. größte  Problem  liegt  aber  meistens  in  der  Verwendung  unterschiedlicher
  303. Library-Funktionen. Hierzu einige Hinweise:
  304.  
  305. Strings
  306.  
  307. Da Herr Wirth nicht das Format von Zeichenketten festlegte, sind mehrere
  308. Formate möglich. Häufig, wie auch bei Megamax Modula, beginnt das erste
  309. Zeichen eines Strings im ersten Element eines ARRAY  0..n  OF CHAR. Die
  310. Zeichenkette, die in solch einem Feld steht, kann entweder das gesamte Feld
  311. ausfüllen oder durch ein Null-Zeichen (0C) begrenzt werden. Die Länge einer
  312. Zeichenkette ist also gleich der Position des ersten Null-Zeichens des Strings
  313. oder gleich der Feldelementanzahl. Es gibt Systeme, die den gesamten unbe~
  314. nutzten Rest des Strings mit Null-Zeichen füllen; bei Megamax Modula ge~
  315. schieht dies nicht - alle Zeichen nach  einem  Null-Zeichen  in  einem  String
  316. werden ignoriert.
  317.  
  318. Es ist theoretisch auch möglich, daß das erste Element eines Strings immer
  319. die  Länge  der  gültigen  folgenden  Zeichen  enthält.  Dann  beginnt  das  erste
  320. Zeichen  einer  Zeichenkette  beim  zweiten  Feldelement,  ein  abschließendes
  321. Zeichen  ist  unnötig.  Diesem  Stringformat  werden  Sie  wahrscheinlich  nicht
  322. begegnen, höchstens, wenn Sie Pascal-Programme übernehmen. In diesem Fall
  323. müssen Sie beachten, daß sich bei indiziertem Zugriff auf Stringelemente die
  324. Positionen der Zeichen alle um Eins verschieben.
  325.  
  326. Die Funktionen in einem Strings-Modul sind nicht normiert. Einige Standard~
  327. funktionen finden sich jedoch in jeder Modula-2 Implementation. Dazu zählen
  328. Pos, Assign, Delete, Insert, Concat (Concatenate) und Length. Letztere wird
  329. sicher nie Probleme bereiten, bei den anderen ergeben sich bis zu drei Unter~
  330. schiede zu anderen  Systemen:  die  Reihenfolge  von  Parametern,  die  Anzahl
  331. derselben und das Verhalten bei Fehlern (Megamax Modula liefert einen BOOLEAN-
  332. Wert, der Fehler anzeigt, andere Systeme stoppen das Programm durch einen
  333. Laufzeitfehler). Das einfachste ist, sich ein Hilfsmodul zu erstellen, das die
  334. benötigten Funktionen mit den Parametern des fremden Systems exportiert und
  335. die Megamax-Strings-Funktionen darüber aufruft.
  336. 5.1 Bibliothek: Allgemeines                                                5 -  8
  337. ________________________________________________________
  338.  
  339.  
  340. Bildschirm E/A (Ein-/Ausgabe)
  341.  
  342. Unsere WriteHex-Routinen geben das '$'-Zeichen selbst mit aus. Wenn Sie
  343. das stört, können Sie statt dessen die WriteNum-Routinen verwenden, die kein
  344. Zeichen voranstellen und auch mit Leerzeichen statt mit Nullen linksseits füllen
  345. können.
  346.  
  347. Die Megamax-Module Terminal, TextWindows, Text und InOut geben Zeichen,
  348. die mit Read eingelesen wurden, nur wieder auf den Bildschirm aus, wenn sie
  349. keine Steuerzeichen, sondern sichtbare Zeichen  sind.  Dies  hat  sich  in  der
  350. Praxis  bewährt.  Programme  für  fremde  Modula-2  Systeme  könnten  davon
  351. abhängig sein, daß jedes eingelesene Steuerzeichen auf den Bildschirm wieder
  352. ausgegeben wird, da dies ursprünglich so vorgeschlagen wurde. In diesem Fall
  353. behelfen Sie sich am besten ebenfalls mit einer Hilfsfunktion, die z. B. wie
  354. folgt aussieht:
  355.  
  356.   PROCEDURE Read ( VAR c: CHAR );
  357.     BEGIN
  358.       InOut.Read ( c );
  359.       IF c <= 37C  (* höchstwertiges Steuerzeichen *) THEN
  360.         Write ( c )  (* Steuerzeichen ausgeben *)
  361.       END
  362.     END Read;
  363.  
  364. Sie können aber auch das Modul Console verwenden - dies gibt jedes einge~
  365. gebene Zeichen gleich wieder aus, aber hat auch noch andere Eigenheiten, die
  366. Sie am besten im Definitionsmodul nachlesen.
  367.  
  368. Ähnlich verhält es sich mit ReadString bei TextWindows, Console und Terminal.
  369. Bei Eingabeende mit der "Return"-Taste bleibt der Cursor hinter dem einge~
  370. gebenen Text stehen anstatt, in die folgende Zeile vorzurücken. Sollte dies
  371. stören, kann ähnlich wie beim obigen Beispiel eine Hilfsprozedur ReadString
  372. deklariert werden, die nach dem entsprechenden Aufruf in Terminal, Console
  373. bzw. TextWindows WriteLn nachfolgend aufruft.
  374.  
  375. Umgekehrt gibt ReadString aus InOut am Ende immer CR/LF aus (springt also
  376. in die nächste Zeile). Ist dies unerwünscht, kann es generell durch Entfernen
  377. des WriteLn-Aufrufs in der entsprechenden Funktion in GEMIO, GEMDOSIO
  378. oder TOSIO verhindert werden  (nach  der  Änderung  muß  das  Treibermodul
  379. nicht nur neu übersetzt, sondern auch in die Shell neu eingelinkt werden, damit
  380. sich die Änderung bemerkbar macht).
  381. 5.1 Bibliothek: Allgemeines                                                5 -  9
  382. ________________________________________________________
  383.  
  384.  
  385. Auch  verhalten  sich  die  Readstring-Funktionen  vieler  Modula-Systeme  beim
  386. Eingeben sehr unterschiedlich. Manche erlauben die Eingabe einer  beliebigen
  387. Zeile bis zum Drücken von Return, andere beenden schon  bei  der  Eingabe
  388. eines  Leerzeichen  oder  lesen  zwar  auf  einmal  eine  ganze  Zeile  ein,  die
  389. folgenden  ReadString-Aufrufe  liefern  aber  immer  nur  Wort-Fragmente,  die
  390. durch eingegebene Leerzeichen getrennt sind.
  391.  
  392. Wir haben deshalb jeweils zwei Funktionen in Terminal und TextWindows dafür
  393. vorgesehen.  Da  diese  Module  als  wählbare  Ein-/Ausgabetreiber  für  InOut
  394. verwendbar sind und durch die Konfigurationsmodule GEMIO und TOSIO, die
  395. wir im Quelltext mitliefern, beliebig an InOut adaptierbar sind, brauchen sie
  396. selbst nur zwei Grundfunktionen zu bieten:
  397.  
  398. * ReadFromLine liest eine Zeile mitsamt aller Control-Codes; bei Dateien wird
  399.   gelesen,  bis  das  Zeilenende  erreicht  oder  der  String  gefüllt  ist,  bei
  400.   interaktiver Eingabe kann so lange korrigiert werden,  bis  sie  mit  Return
  401.   abgeschlossen wird. Es gibt hier auch noch die  Funktion  ReadString,  die
  402.   lediglich noch vorhanden ist, damit Megamax-Programme, die für die alte
  403.   System-Version  Eins,  in  der  es  noch  kein  ReadFromLine  gab,  ohne
  404.   Änderungen  weiterhin  übersetzbar  bleiben.  ReadString  sollte  hier  aber
  405.   überhaupt  nicht  mehr  verwendet  werden,  sondern,  je  nach  Bedarf,
  406.   ReadToken oder ReadFromLine (Normallfall).
  407.  
  408. * ReadToken ermöglicht lediglich die Eingabe eines Wortes - sobald ein Leer-
  409.   oder Control-Zeichen (also auch Return) eingegeben wird, kehrt ReadToken
  410.   zurück.
  411.  
  412. InOut greift nun über ein Treibermodul (z.B. GEMIO, TOSIO, GEMDOSIO) auf
  413. diese Funktionen zu. Dazu bietet es ebenfalls die Funktionen  ReadFromLine,
  414. ReadToken  und  ReadString:  Wie  sich  diese  Funktionen  verhalten,  wird  im
  415. Treibermodul bestimmt. So ist es  möglich,  ReadString  entweder  direkt  auf
  416. ReadToken oder ReadFromLine abzubilden, oder  mit  Hilfe  von  ReadFromLine
  417. eine gepufferte Eingabe zu realisieren, die auch bei Read-Aufrufen aus der
  418. gepufferten Zeile liest. Das soll Sie aber nicht verwirren, deshalb sparen wir
  419. uns nun weitere Erklärungen - verstehen Sie es einfach  so:  Benutzen  Sie
  420. möglichst nur ReadFromLine/ReadToken (egal, ob aus Terminal, TextWindows
  421. oder InOut importiert) - wenn Sie einmal mit dem Übertragen eines Modula-
  422. Programms von oder zu einem anderen System konfrontiert werden, werden
  423. Sie  diese  Unterschiede  erkennen  und  dann  auch  durchschauen,  welche
  424. Änderungen Sie an den Treibermodulen vornehmen müssen.
  425.  
  426. Wie schon erwähnt, sind also ggf. die Treiber GEMIO oder TOSIO für die
  427. Konfiguration  der   InOut-Funktionen   verantwortlich:   Die   unterschiedlichen
  428. Konfigurationen müssen durch abgewandelte Versionen der Module GEMIO und
  429. TOSIO erstellt werden. So könnte man ein JPI IO erstellen, um die TopSpeed-
  430.                                                 _
  431. IO-Module nachzubilden, eine  HM2 IO  für  Hänisch-Modula-Programme  usw.
  432.                                      _
  433. Solch ein Modul muß dann als erstes Modul im Hauptprogramm - also vor
  434. 5.1 Bibliothek: Allgemeines                                                5 - 10
  435. ________________________________________________________
  436.  
  437.  
  438. InOut - importiert werden. Dies wird übrigens auch empfohlen, wenn Sie bei
  439. normalen Megamax-Programmen, die InOut verwenden, die Ausgaben nicht in
  440. ein Fenster bekommen wollen: Schreiben Sie einfach
  441.  
  442.   IMPORT TOSIO; (*$E MOS *)
  443.  
  444. vor den InOut-Import. Dann wird erstens das TOSIO-Modul, wie beim Linken,
  445. als InOut-Treiber verwendet, zweitens wird die Endung MOS erzeugt, was für
  446. einen TOS-Bildschirm (Textcursor, keine Maus) beim Starten sorgt.
  447.  
  448. Bereits  in  Planung  ist  ein  komfortableres  Konzept  für  die  nächste  Shell-
  449. Version: Dann können Sie für jedes Modul individuell die Umgebung dauerhaft
  450. bestimmen, also seine Stack-Größe, die einzubindenden Treiber (sowohl für's
  451. Starten  mit  Load-Time-Linking  als  auch  beim  festen  Linken)  und  andere
  452. nützliche Konfigurationen, die von außen bestimmbar sein sollten.
  453.  
  454. Wenn Sie übrigens eigene Konfigurations- oder InOut-Treibermodule (z.B. für
  455. andere Modula-Systeme) erstellt haben, senden Sie sie doch im Rahmen des
  456. MEMOX-Service (s. Kapitel 1.5) an Application Systems! Damit helfen Sie nicht
  457. nur  den  anderen  Megamax-Anwendern  (auch  uns,  damit  wir  uns  anderen
  458. Dingen widmen können, bei denen Sie uns nicht helfen könnten), sondern Sie
  459. erhalten dafür ja auch Beiträge anderer Anwender.
  460.  
  461.  
  462. Hinweise zu den Quelltexten
  463.  
  464. Um Ihnen als Anwender die Möglichkeit zu geben, den Dialog mit dem Modula-
  465. System  nach  Ihren  Wünschen  optimal  zu  gestalten,  haben  wir  die  dafür
  466. zuständigen Module im Sourcetext mitgeliefert.  Die  interessantesten  Module
  467. sind  im  folgenden  aufgeführt,  es  lohnt  sich  aber  auch,  sich  die  anderen
  468. Sourcetexte (siehe UTILITY-, DEMO- und MOS-Ordner) einmal anzusehen.
  469.  
  470.  
  471. MM2SHELL.M
  472.  
  473. Dies ist die Modula-2 Shell, das Desktop des Modula-Systems. Sie können
  474. sie beliebig verändern und erweitern. Außerdem lassen sich darin viele Bei~
  475. spiele für Programmieranwendungen finden, z. B. Zugriff auf GEM-Funktionen,
  476. Aufruf von Programmen oder Dateizugriffe. Dazu gehören auch die  Dateien
  477. MM2SHELL.RSC und MM2SHELL.RSD, die mit Hilfe des Resource Construction
  478. Programms  (RCP)  verändert  werden  können.  Beachten  Sie,  daß  nach  dem
  479. Ändern der Resource  mit  dem  RCP  beim  neuen  Abspeichern  zwei  Dateien
  480. MM2SHELL.D  und  MM2SHELL.I  erzeugt  werden,  die  die  Konstanten  der
  481. GEM-Objekte enthalten und von der Shell importiert werden. Allerdings müssen
  482. die  Modulnamen  in  den  beiden  Quelltexten  dazu  erst  von  Mm2shell  in
  483. Mm2shellRsc umbenannt werden!
  484. 5.1 Bibliothek: Allgemeines                                                5 -  11
  485. ________________________________________________________
  486.  
  487.  
  488. GEMError.I & SimpleError.I
  489.  
  490. Diese Module werden bei Bedarf beim Linken von Programmen als Treiber mit
  491. eingebunden. Sie sorgen für das Abfangen und Anzeigen aller Laufzeitfehler.
  492. Zudem enthalten sie die  Texte  für  Systemmeldungen,  die  nach  Belieben  in
  493. Englisch oder auch Esperanto übersetzt werden können.
  494.  
  495.  
  496. MOSConfig.I
  497.  
  498. Hierin sind  globale  Variable  enthalten,  die  von  verschiedenen  MOS-Modulen
  499. verwendet  werden.  Im  Sourcetext  können  die  Voreinstellungen  nach  Ihren
  500. Preferenzen  verändert  werden,  z.  B.  Datumsformat  (für  Funktionen  aus
  501. TimeConvert) oder Zahlendarstellungsformate (für REAL-Darstellungen).
  502.  
  503.  
  504. Bedienung der Ein-/Ausgabefunktionen
  505.  
  506. Viele Funktionen der Megamax-Bibliothek bieten auch in der Benutzung über~
  507. durchschnittlichen Komfort, verglichen mit anderen Entwicklungssystemen auf
  508. Microcomputern.
  509.  
  510. Besonders offensichtlich  ist  das  beispielsweise  bei  Verwendung  des  InOut-
  511. Moduls durch das StdIO-Fenster, in dem die Ausgaben geschehen. Wartet das
  512. Programm auf eine Eingabe, macht es dauernd Ausgaben oder benutzt andere
  513. GEM-Funktionen, so daß die Event-Abfrage vom GEM regelmäßig aktiviert wird
  514. (beispielsweise  ist  dies  auch  durch  regelmäßige  Aufrufe  der  Prozedur
  515. FlushEvents aus dem Modul  EventHandler  zu  erreichen).  Das  Fenster  kann
  516. bewegt, in seiner Größe verändert und der Ausschnitt mit der Maus bestimmt
  517. werden.
  518.  
  519. Weniger offensichtlich sind da schon die Editiermöglichkeiten bei Benutzung der
  520. Funktionen ReadString, ReadFromLine und ReadToken. Nicht nur, daß mit der
  521. Taste Backspace Korrekturen möglich sind, auch viele andere Tasten haben
  522. eine Funktion:
  523.  
  524.     Return                Beendet Eingabe
  525.     Enter                 Wie Return
  526.     Undo                 Bricht Eingabe ab (liefert Leerstring)
  527.     <
  528.      -                    Cursor nach links
  529.      >
  530.     -                     Cursor nach rechts
  531.              <
  532.     Control  -            Zum Zeilenbeginn
  533.               >
  534.     Control -             Zum Zeilenende
  535.     Insert                Ein Leerzeichen an Cursorposition einfügen
  536.     Backspace            Zeichen vor Cursor löschen
  537.     Delete                Zeichen unter Cursor löschen
  538.     Esc                   Zeile löschen
  539.     Clr (Shift-Home)     Wie Esc
  540.     Home                 Zeile ab Cursor löschen
  541. 5.1 Bibliothek: Allgemeines                                                5 - 12
  542. ________________________________________________________
  543.  
  544.  
  545. Ein weiteres Geheimnis, das nur diejenigen bisher erkannten, die die Doku~
  546. mentation zu den Funktionen in Convert aufmerksam gelesen haben, wollen wir
  547. nun lüften:
  548.  
  549. Die Convert-Funktionen zum Umwandeln von Zeichenfolgen in Zahlen erlauben,
  550. daß  die  Werte  mit  einem  "$"-  oder  "%"-Zeichen  angeführt  werden.  Dies
  551. bewirkt dann eine Interpretation des Wertes als hexadezimale bzw. als binäre
  552. Zahl.  Da  alle  Funktionen  des  Megamax-Systems,  die  Texte  in  irgendeiner
  553. Weise in Zahlen umwandeln, letztlich auf dieses Convert-Modul zurückgreifen
  554. (wozu haben wir uns schließlich für Modula-2 entschieden?!), können Sie also
  555. auch bei einem ReadCard-Aufruf statt "21" nun "$15" oder gar "%100000101"
  556. eingeben!
  557.  
  558.  
  559. Diverse Hinweise zu den Bibliotheken
  560.  
  561. GEMDOSIO- und TOSIO-Ausgabe
  562.  
  563. Geschehen die Ein-/Ausgaben über das Modul InOut, kann bekanntlich beim
  564. Linken durch die Linker-Optionen bestimmt  werden,  ob  GEMDOSIO,  TOSIO
  565. oder GEMIO verwendet werden  soll.  Bei  Modulen,  die  mit  Loadtime-Linking
  566. unter der Shell gestartet werden, ist diese Wahl nicht so einfach möglich.
  567. Normalerweise  wird  die  Konfiguration  verwendet,  mit  der  die  Shell  gelinkt
  568. wurde:  mit  GEMIO.  Der  GEMDOS-  oder  TOSIO-Treiber  kann  dennoch
  569. verwendet werden: Schreiben Sie folgendes in eine Zeile vor dem InOut-Import
  570. im betreffenden Programm:
  571.   IMPORT TOSIO; (*$E MOS *) (bzw. GEMDOSIO statt TOSIO)
  572. Damit  wird  beim  Starten  des  Programms  automatisch  der  TOS-Modus
  573. aktiviert.  Zu  beachten  ist  jedoch,  daß  beim  Linken  der  Import  aus  dem
  574. Programm  wieder  entfernt  werden  muß,  wenn  dort  ein  anderes  IO-Modul
  575. eingelinkt werden soll.
  576.  
  577. Speicheranforderung mit ALLOCATE (Storage-Modul)
  578.  
  579. Dem  kommenden  ISO-Standard  für  Modula  nach  wird  ALLOCATE  keinen
  580. Laufzeitfehler auslösen, wenn kein Speicher mehr verfügbar ist, sondern den
  581. Zeiger mit NIL beschreiben.
  582.  
  583. Zweitens  dürfen  Sie  nie  davon  ausgehen,  daß  der  angeforderte  Speicher
  584. gelöscht, d.h. mit Null-Bytes gefüllt, ist. Beachten Sie auch, daß die globalen
  585. Variablen bei Megamax Modula-2 zwar mit Null-Werten vorbesetzt  werden,
  586. nach  PIM  und  dem  ISO-Standard  dies  aber  nicht  gefordert  ist,  Sie  bei
  587. Portierung Ihrer Module demnach damit rechnen müssen, daß dies auf einem
  588. anderen Compiler/Rechner auch nicht der Fall ist.
  589. 5.1 Bibliothek: Allgemeines                                                5 - 13
  590. ________________________________________________________
  591.  
  592.  
  593. Verwendung von AES- und VDI-Funktionen (Maus-Funktionen und FormAlert)
  594.  
  595. Sie sollten bei GEM-Programmen darauf achten, niemals auf VDI-Funktionen
  596. zurückzugreifen, wenn entsprechende Funktionen im AES vorhanden sind. Denn
  597. dort, wo das AES eigene Funktionen auf das VDI "aufsetzt", hat letztendlich
  598. auch  das  AES  die  Kontrolle,  und  Sie  können  unliebsame  Seiteneffekte
  599. hervorrufen, wenn Sie das AES durch direktes Anwenden des VDI umgehen.
  600.  
  601. Beliebtes Beispiel ist die Kontrolle der Maus: Es gibt die VDIInput-Prozeduren
  602. ShowMouse  und  HideMouse  sowie  GrafMouse  in  AESGraphics.  Hier  hat
  603. demnach das AES Vorrang. Wird ein Programm vom Desktop gestartet, wird
  604. die Maus über GrafMouse eingeschaltet. Wenn Sie nun in Ihrem Programm die
  605. Maus mit HideMouse abschalten, verschwindet sie zwar, das AES erfährt aber
  606. nichts davon, denkt also, sie sei noch sichtbar. Kommt nun eine AES-Funktion
  607. zum Zuge, die die Maus einschalten will, beispielsweise GrafMouse oder auch
  608. FormAlert  (diese  Funktion  versucht  selbstständig,  die  die  Maus  immer
  609. einzuschalten), geht das AES davon aus, die Maus sei sichtbar und teilt dem
  610. VDI deshalb auch nicht mit, die wirklich einzuschalten. Der Effekt: Die Maus
  611. ist nicht zu sehen. Fazit: Lassen Sie die Finger von Show- und HideMouse!
  612.  
  613. Der richtige Gebrauch der UpdateWindow-Funktion...
  614.  
  615.     ... bei der Accessory-Initialisierung
  616.  
  617. Bei der Programmierung eines jeden Accessories sollten Sie folgende Regel
  618. beachten: Zuerst der Aufruf von InitGem, danach RegisterAccessory und - dies
  619. ist  besonders  wichtig  -  UpdateWindow  (TRUE).  Erst  dann  dürfen  eine
  620. GEM-Resource-Datei nachgeladen, Speicher angefordert und andere Betriebs~
  621. systemressourcen "geöffnet"  werden.  Am  Ende  der  Initialisierung,  also  vor
  622. dem Event-Aufruf, muß  dann  noch  der  Aufruf  von  UpdateWindow  (FALSE)
  623. nachgeholt  werden!  Siehe  dazu  beispielsweise  das  Demo-Programm  Timer
  624. (UTILITY-Ordner).
  625.  
  626. Wird  das  nicht  beachtet,  können  u.U.  schon  während  der  Initialisierung
  627. Task-Wechsel zu anderen Accessories und insbesondere ein GEM-Programm
  628. per Autostart-Option gestartet werden und so dann die im  Kapitel  zu  den
  629. Sys-Funktionen beschriebenen Fehler auftreten. (Ein ausführlicher Artikel dazu
  630. findet sich im ST-Magazin 11/90 auf Seite 68. Ein Dank an Laurenz Prüßner,
  631. der darin diese GEM-"Macke" aufgedeckt hat!)
  632.  
  633.     ... bei Timer-Events mit GEMDOS-Aufrufen
  634.  
  635. Bekanntlich ist UpdateWindow dann zu benutzen, wenn Sie Manipulationen am
  636. Bildschirm  vornehmen,  also  bei  Benutzung  bestimmter  AES-  und  VDI-
  637. Funktionen.  Ansonsten,  z.B.  bei  GEMDOS-  und  BIOS-Funktionen,  wird  dies
  638. allgemein nicht für nötig gehalten. Das ist aber leider falsch! Wenn nämlich
  639. aus bestimmten Gründen dabei eine Alert-Box erscheint, können Accessories,
  640. 5.1 Bibliothek: Allgemeines                                                5 - 14
  641. ________________________________________________________
  642.  
  643.  
  644.  
  645. die  auf  einen  Timer-Event  warten,  zum  Zuge  kommen.  Diese  wiederum
  646. könnten  einen  GEMDOS-Aufruf  tätigen.  Wenn  aber  gerade  die  Haupt~
  647. anwendung selbst einen GEMDOS-Aufruf vornahm, ergibt das einen unerlaubten
  648. Wiedereintritt ins GEMDOS, die Folge ist ein Absturz des Rechners.
  649.  
  650. Wie  kann  es  dazu  kommen?  Die  besagte  Alert-Box  erscheint,  wenn  eine
  651. Funktion  aufgerufen  wird,  die  den  Critical  Error  Handler  aufruft,  weil
  652. beispielsweise keine Disk im Laufwerk  steckt  oder  weil  sie  nicht  gelesen/
  653. beschrieben werden kann. Die FormAlert-Routine des GEM verhindert in diesen
  654. Fällen aber  nicht,  daß  Timer-Events  ausgewertet  werden  und  so  kann  ein
  655. Accessory zum Zuge kommen. Der eigentliche Fehler passiert aber erst dann,
  656. wenn  das  Accessory  einen  Wiedereintritt  ins  GEMDOS  vornimmt.  Dies  ist
  657. praktisch immer der Fall, wenn der Critical Error Handler aktiviert wurde, weil
  658. dann ja meist gerade ein Diskzugriff über die GEMDOS-Funktionen erfolgt.
  659.  
  660. Was  ist  also  zu  tun?  Wenn  Sie  Timer-Events  behandeln,  müssen  Sie
  661. währenddessen   auch   alle   evtl.   vorkommenden   GEMDOS-Aufrufe   durch
  662. UpdateWindow einklammern! Da Sie bei Verwendung der Modula-Bibliotheks~
  663. funktionen sich dessen u.U. nicht sicher sein können, klammern Sie am besten
  664. die ganze Timer-Event-Behandlung entsprechend ein.
  665.  
  666. Sie können den Fehler übrigens leicht probeweise hervorrufen: Nehmen Sie das
  667. Timer-Accessory (UTILITY-Ornder) und entfernen Sie aus der Event-Schleife,
  668. in der die Zeit neu ausgegeben wird, die UpdateWindow-Aufrufe. Installieren
  669. Sie dann das Accessory, wie dort angegeben. Wenn Sie nun einen Diskfehler
  670. erzeugen, indem Sie z.B. Laufwerk A: ohne eine Disk darin öffnen, werden Sie
  671. eine Alert-Box erhalten  und  die  Uhr  wird  währenddessen  weiterlaufen.  Bei
  672. Bestätigung  der  Alert-Box  erhalten  Sie  dann  einen  Systemabsturz  (das
  673. Timer-Modul ruft über das Clock-Modul indirekt eine GEMDOS-Funktion auf,
  674. die die aktuelle Zeit ermittelt).
  675.  
  676. Die FPU und Accessories
  677.  
  678. Die Entwickler von Atari empfehlen, die FPU in Accessories nicht zu benutzen.
  679. Der Grund dafür liegt darin, daß im TOS keine Funktionen vorgesehen sind, die
  680. das  Benutzen  der  FPU  von  mehreren  GEM-Tasks  (Hauptprogramm  und
  681. Accessories)  regelt.  Wenn  beispielsweise  die  Register  der  FPUmit  Werten
  682. belegt sind, und dann ein anderes Accessory zum Zuge käme und auch die
  683. FPU benutzt, würde sie wahrscheinlich die Register-Werte überschreiben. So
  684. denkt Atari.
  685.  
  686. Wir  haben  zur  Lösung  das  Modul  FPUSupport  geschaffen.  Das  bietet
  687. Funktionen  zum  Retten  und  Restaurieren  des  gesamten  FPU-Status  incl.
  688. Register und sonstiger Einstellungen (z.B. Rundungsmodus). Wollen Sie also in
  689. einem Accessory die FPU benutzen, sehen Sie sich dieses  Modul  an.  Dort
  690. finden Sie die weiteren Hinweise.
  691. 5.2 Bibliothek: Programme, Module und Prozesse                         5 - 15
  692. ________________________________________________________
  693.  
  694.  
  695. 5.2  Programme,  Module  und  Prozesse
  696.  
  697.  
  698. Das Modulkonzept
  699.  
  700. Als Programme werden im Folgenden alle die Dateien bezeichnet, die z.B. vom
  701. Desktop aus direkt ausgeführt werden können. Als Module werden die vom
  702. Modula-2 Compiler erzeugten Code-Dateien bezeichnet.
  703.  
  704. Auch Compiler für andere Sprachen erzeugen in der Regel nicht sofort aus~
  705. führbare Dateien.  Statt  dessen  müssen  diese  Dateien  mit  weiteren,  schon
  706. compilierten Dateien (die die "importierten" Funktionen und Variablen enthal~
  707. ten),  zusammengelinkt  (gebunden)  werden.  Das  TOS  (Betriebssystem  des
  708. Atari)  bietet  nun  eine  Funktion,  mit  der  solche  Programme  geladen  und
  709. gestartet werden können. Diese wird z.B. aktiviert, wenn man eine Programm~
  710. datei auf dem Desktop doppelt anklickt. Aber auch ein gestartetes Programm
  711. kann wiederum ein weiteres aufrufen.
  712.  
  713. Im MOS (Modula-2 Betriebssystem) gibt es eine Funktion, die in der gleichen
  714. Weise  Module  zum  Ausführen  laden  kann.  Das  Dazuladen  und  Linken  der
  715. importierten Module wird dabei automatisch  erledigt.  Dabei  werden  nur  die
  716. importierten Module nachgeladen, die sich noch nicht im  Speicher  befinden.
  717. Schon  vorhandene  Module  werden  ganz  einfach  von  den  neuen  Modulen
  718. mitbenutzt.
  719.  
  720. Damit man die Ladefunktion des MOS  überhaupt  benutzen  kann,  muß  erst
  721. einmal  ein  Programm  gestartet  werden,  das  diese  Funktion  enthält.  Die
  722. Funktion kann sich nur in  einem  Programm  der  herkömmlich  gelinkten  Art
  723. befinden, und das Programm muß über die TOS-Ausführungsfunktion gestartet
  724. werden. Ein solches Programm besteht aus mehreren Modulen, die dann aber
  725. alle schon als vorhanden registriert werden, so daß, wenn dann ein anderes
  726. Modul  gestartet  werden  soll,  die  im  Programm  vorhandenen  Module  mit~
  727. verwendet werden können (shared code).
  728.  
  729. Praktisch sieht das also z.B. so aus: Man hat ein Hauptprogramm H1, das die
  730. Module U1, U2 und U3 importiert. Dieses Programm soll vom normalen Desktop
  731. aus gestartet werden können. Dazu wird es mit dem Linker gebunden.
  732.  
  733. Wenn das gelinkte Programm dann durch Doppelklick gestartet wird, befinden
  734. sich die Module H1, U1 U2 und U3 im Speicher. Enthalte U1 nun die MOS-
  735. Funktion zum Starten weiterer Module. Dann kann z.B. in H1 programmiert
  736. worden sein, ein Modul H2 nachzustarten. H2 importiert außerdem U2 und U4.
  737. Wenn es nun  über  die  MOS-Ausführungsfunktion  gestartet  wird,  wird  das
  738. Modul U4 nachgeladen. Die importierten Prozeduren aus U2 werden aus dem
  739. schon vorhandenen Modul mitverwendet, lediglich die Variablen werden bei U2
  740. ein weiteres Mal angelegt.
  741. 5.2 Bibliothek: Programme, Module und Prozesse                         5 - 16
  742. ________________________________________________________
  743.  
  744.  
  745. Wenn man das gleiche unter TOS anstellen wollte, nämlich, daß ein Programm
  746. ein zweites nachstartet, müßten beide Programme mit jeweils allen benötigten
  747. Modulen gelinkt sein, was bedeuten würde, daß das erste Programm aus H1,
  748. U1, U2 und U3 bestünde und das Nachgeladene aus H2, U2 und U4. Somit
  749. würde ein Modul zwangsläufig doppelt im Speicher vorliegen, was unnötigen
  750. Speicherplatz verbräuchte.
  751.  
  752. Das  automatische  Linken  beim  Ausführen  macht  sich  besonders  bei  der
  753. mitgelieferten Modula-Shell positiv bemerkbar. Während die Shell durch viele
  754. importierte  Module  ziemlich  viel  Speicher  belegt,  belegen  viele  Modula-
  755. Programme,  die  von  der  Shell  aus  gestartet  werden,  kaum  zusätzlichen
  756. Speicher,  da  meistens  schon  alle  benötigten  Module  von  der  Shell  zur
  757. Verfügung gestellt werden können.
  758.  
  759. Ein weiterer Vorteil liegt darin, daß durch gemeinsame Benutzung von Variablen
  760. mehrere nacheinander gestarteten Module Daten übermitteln können. Z.B. wird
  761. das Modul ShellMsg von der Shell und dem Compiler importiert. Dadurch kann
  762. der Compiler, bevor er  endet,  in  den  dort  deklarierten  Variablen  z.B.  den
  763. Namen der erzeugten Codedatei oder bei einem Fehler den Fehlertext ablegen,
  764. und die Shell kann diese Daten dann weiterverwenden. Diese Option (shared
  765. data) muß allerdings erst über eine besondere Compiler-Direktive ($Y, s. Kap.
  766. 3.4) angewählt werden.
  767.  
  768.  
  769. Vom Modul zum gelinkten Programm
  770.  
  771. Die gesamten MOS-Funktionen wurden so konzipiert, daß ein Programm erst
  772. als Modul unter der Modula-Shell getestet werden kann und am Ende, falls
  773. dies  vonnöten  ist,  möglichst  ohne  Änderungen  mit  all  seinen  importierten
  774. Modulen zu einem Programm zusammengelinkt werden kann, das dann  vom
  775. Desktop aus gestartet werden kann. In wenigen Fällen muß jedoch eine Anpas~
  776. sung des zu linkenden Programms durchgeführt werden.
  777.  
  778. Wenn  das  von  der  Shell  gestartete  Modul  mit  SetChain  einen  Nachfolger
  779. bestimmt, kann dies nicht mehr geschehen, wenn das diese Funktion aufrufen~
  780. de Modul gelinkt ist und übers TOS gestartet wird. Denn das Nachladen des
  781. Folgeprogramms kann nur vom Aufrufer erledigt werden, und das  TOS  als
  782. Aufrufer läßt dies nicht  zu.  Solange  das  Modul  von  der  Shell  mittels  der
  783. Loader-Funktion CallModule gestartet wird, kann diese Funktion nach Ende des
  784. ersten Moduls das nächste nachstarten. Wenn Sie nun also  ein  Programm
  785. geschrieben haben, das aus mehreren, sich abwechselnd nachladenden Modulen
  786. besteht, sollten die Module nie gelinkt werden. Statt dessen sollten Sie ein
  787. Hilfsmodul erstellen, das gelinkt wird und vom Desktop gestartet werden kann.
  788. Es importiert lediglich die Funktion CallModule und startet  damit  das  erste
  789. Modul. Dieses Modul kann dann wiederum andere mittels SetChain nachstarten,
  790. da ja bei Modulende immer zum Hilfsprogramm zurückgekehrt wird.
  791. 5.2 Bibliothek: Programme, Module und Prozesse                         5 - 17
  792. ________________________________________________________
  793.  
  794.  
  795. Allerdings kann auch die Funktion ShellWrite (Modul AESMisc) benutzt werden,
  796. um vom Desktop gestartete Programme - ähnlich SetChain - zu verketten.
  797.  
  798. Ein  Fehler,  der  häufiger  vorkommt,  entsteht  nur  bei  optimiertem  Linken:
  799. Während  der  Loader  jedes  importierte  Modul  vollständig  einbindet  und
  800. initialisiert, kann der optimierende Linker Module ganz entfernen, obwohl sie
  801. importiert  werden.  Dies  passiert  beispielsweise,  wenn   sie   ein   Modul
  802. importieren, ohne Prozeduren oder Variablen daraus zu benutzen. Initialisiert
  803. das  Modul  in  seinem  Körper  Daten  importierter  Module,  würden  diese
  804. Anweisungen beim optimierten Linken verschwinden.
  805.  
  806. Dieser Effekt kann leicht daran erkannt werden, daß beim Linken solch ein
  807. Modul erst im Fenster angezeigt, dann aber wieder gelöscht wird. In diesem
  808. Fall braucht das Modul lediglich mit der Direktive B+ übersetzt werden, am
  809. besten, indem gleich zu Beginn des Moduls (*$B+*) eingefügt wird.
  810.  
  811. Zur  Sicherheit  kann  auch  erstmal  das  Programm  nicht-optimiert  gelinkt
  812. oder generell  durch  Eintragen  von  -B  in  der  Compiler-Direktiven-Zeile  der
  813. Shell jedes Ihrer Module entsprechend übersetzt werden.
  814.  
  815. Wenn Sie diese Sonderfälle berücksichtigen, ist ein Modul, das unter der Shell
  816. lief, auch als "eigenständiges" Programm lauffähig. Es stellt sich jedoch die
  817. Frage,  was  passieren  soll,  wenn  wider  Erwarten  doch  noch  Fehler  im
  818. Programm  auftreten.  Unter  der  Shell  werden  automatisch  Fehleranzeigen
  819. ausgelöst. Die Funktionen sind dazu  von  der  Shell  installiert  worden.  Auch
  820. solche Funktionen müssen beim Linken extra eingebunden werden. Es gibt hier
  821. einmal die Möglichkeit, das Modul GEMError einzubinden, das auch von der
  822. Shell zur Fehlerbehandlung importiert wird. Wem das zuviel ist, der kann die
  823. abgespeckte  Version  SimpleError  verwenden  oder  einen  der  mitgelieferten
  824. Quelltexte modifizieren: Wenn die Variablen von FileBase unverändert bleiben,
  825. werden  Dateien  bei   Programmende   immer   ohne   Meldung   automatisch
  826. geschlossen, Fehler immer ignoriert, und die Files-Funktion GetStateMsg liefert
  827. immer einfach eine Fehlernummer statt des passenden Textes. Also kann man,
  828. falls man sich seines Dateiumgangs sicher ist, die FileBase-Operationen aus
  829. dem eigenen GEMError entfernen.
  830.  
  831. Bei  den  Laufzeitfehlern  sollte  man  zumindest  eine  einfache  Fehlermeldung
  832. weiterhin vornehmen, denn wenn die Fehler nicht abgefangen werden, gibt es
  833. höchstens diese häßlichen Bomben, und das Programm terminiert sofort, ohne
  834. daß man feststellen kann, was passiert ist.
  835.  
  836. Über die Laufzeitfehlerbehandlung  existiert  ein  ausführliches  Kapitel  zu  den
  837. Modulen Excepts, ErrBase, HdlError und EasyExceptions.
  838. 5.2 Bibliothek: Programme, Module und Prozesse                         5 - 18
  839. ________________________________________________________
  840.  
  841.  
  842. Ein Sonderfall ist die Verwendung des Moduls InOut. Unter der Shell werden
  843. Ausgaben über dieses Modul in einem Window  dargestellt.  InOut  importiert
  844. selbst nicht das dafür verwendete Modul TextWindows,  sondern  InOutBase.
  845. Unter der Shell sind allerdings die TextWindows-Funktionen darauf zugewiesen.
  846. Wenn ein Programm, das InOut benutzt, gelinkt wird, muß ein Konfigurations~
  847. modul mit eingebunden werden, das diese Prozedurvariablen initialisiert. Dazu
  848. stehen  wahlweise  GEMIO,  TOSIO  oder  GEMDOSIO  zur  Verfügung.  GEMIO
  849. importiert TextWindows und weist dessen Funktionen auf die Prozedurvariablen
  850. in InOutBase zu, eben wie dies auch in der Shell geschieht. TOSIO dagegen
  851. verwendet statt dessen die Funktionen aus Terminal für InOut und GEMDOSIO
  852. verwendet das Console-Modul, sodaß auch Ein-Ausgabeumlenkung von außen
  853. möglich ist, beispielsweise durch die Benutzung von Command-Line-Shells. Das
  854. bewirkt,  daß  ein  Programm,  das  TOSIO  oder  GEMDOSIO  statt  GEMIO
  855. eingebunden  hat,  die  Ausgaben  nicht  auf  ein  Window  tätigt,  sondern  den
  856. gesamten Bildschirm dafür verwendet. In  diesem  Fall  sollten  keine  anderen
  857. GEM-Funktionen verwendet und das gelinkte Programm mit der Endung ".TOS"
  858. statt ".PRG" benannt werden.
  859.  
  860. Sie können vor dem Linken eines Programm durch Aufruf der Linker-Optionen
  861. bestimmen, ob Sie GEMIO, GEMDOSIO oder TOSIO einbinden wollen. Ersteres
  862. ist in der Anwendung optisch sicher schöner, die anderen benötigen wegen
  863. sparsamerer Importe weniger Speicherplatz.
  864.  
  865. Wenn Sie in dem zu linkenden Programm InOut nicht verwenden, brauchen Sie
  866. GEMIO, GEMDOSIO bzw. TOSIO auch nicht einzubinden. Wenn Sie vergessen,
  867. eines der Module einzubinden, obwohl InOut benutzt wird, erhalten Sie, wenn
  868. Sie das Programm dann starten,  eine  Fehlermeldung  mit  dem  Text  "InOut
  869. driver is missing!".
  870.  
  871.  
  872. Prozesse
  873.  
  874. Wenn ein Programm unter TOS gestartet wird (also z.B. vom Desktop aus),
  875. richtet das TOS dafür einen Prozeß ein (Der Prozeßbegriff ist nicht mit den
  876. Modula-2 Coroutinen zu verwechseln!). In der Praxis bedeutet dies, daß sich
  877. das TOS merkt, daß ein neues Programm gestartet wurde und von nun an
  878. bestimmte   Systemresourcen   (z.B.   Speicheranforderungen,   Dateizugriffe)
  879. diesem  Prozeß/Programm  zugeordnet  werden.  Wenn  das  Programm/der
  880. Prozeß  endet,  können  alle  Systemresourcen  des  Programms  erkannt  und
  881. notfalls freigegeben werden (z.B. belegter Speicher wieder freigegeben, offene
  882. Dateien geschlossen).
  883.  
  884. Gegenüber  einem  einfachen  Unterprogramm  hat  ein  Prozeß  außerdem  den
  885. Vorteil, daß er sich zu (fast) jeder Zeit und an jeder Programmstelle beenden
  886. kann und die Ausführung dann immer hinter der Programmstelle fortgeführt
  887. wird, die den Prozeß gestartet hat (wie bei einem Unterprogrammaufruf).
  888. 5.2 Bibliothek: Programme, Module und Prozesse                         5 - 19
  889. ________________________________________________________
  890.  
  891.  
  892. Jeder  Prozeß  erhält  eine  Basepage.  Dies  ist  ein  Speicherbereich  von  256
  893. Bytes, in denen bestimmte Daten angelegt werden, die der Prozeß ganz privat
  894. benötigt (ähnlich dem Workspace bei Modula-Coroutinen). Darin wird z.B. eine
  895. Textzeile abgelegt, die der Aufrufer übergeben hat (z.B. die Argumentzeile bei
  896. ".TTP"-Programmen) und die offenen Dateien registriert.
  897.  
  898. Wenn ein Programm / Prozeß endet, kann es dem Aufrufer eine Nachricht in
  899. Form einer INTEGER-Zahl (-32768 bis 32767) liefern. Es ist sinnvoll, negative
  900. Werte zu liefern, wenn ein Fehler im aufgerufenen Programm auftrat, und Null,
  901. wenn nichts Besonderes zu melden ist.
  902.  
  903. Im MOS (Modula Operating System) gibt es zwei Möglichkeiten, einen Prozeß
  904. zu starten. Entweder man startet ein Programm oder Modul mit der Funktion
  905. CallModule aus dem Modul Loader oder man startet ein Unterprogramm als
  906. Prozeß mit CallProcess aus ModCtrl. Solch ein Prozeß kann dann auf zwei
  907. Arten  zu  Ende  geführt  werden.  Entweder  läuft  das  Programm  bzw.  das
  908. Unterprogramm  bis  zum  Ende  durch  oder  es  wird  auf  irgend  eine  Weise
  909. TermProcess  aus  PrgCtrl  aufgerufen.  Bei  normaler  Beendigung  wird  als
  910. Ergebnis des Prozesses eine Null über CallModule bzw. CallProcess geliefert,
  911. bei  Aufruf  von  TermProcess  kann  ein  selbst  gewählter  Ergebniswert  (die
  912. INTEGER-Zahl) übergeben werden.
  913.  
  914. TermProcess wird z.B.  automatisch  ausgeführt,  wenn  ein  Programm  durch
  915. einen Laufzeitfehler unterbricht und bei der dann angezeigten Fehlermeldung
  916. "Quit" oder "Abbruch" angewählt wird. Als Ergebniswert wird dann an  den
  917. CallModule-   bzw.   CallProcess-Aufrufer   die   Laufzeitfehlernummer   (s.
  918. MOSGlobals) geliefert.
  919.  
  920. CallModule  kann  sowohl  normale  Programme  als  auch  die  vom  Compiler
  921. erzeugten, ungelinkten Module starten. Wird  ein  Modula-2  Modul  gestartet,
  922. werden alle importierten Module, die sich noch nicht im  Speicher  befinden,
  923. nachgeladen.  Wenn  der  Prozeß  endet,  werden  alle  nicht  mehr  benötigten
  924. Module  wieder  freigegeben,  d.h.,  daß  der  von  ihnen  belegte  Speicherplatz
  925. wieder für neue Daten frei wird.
  926.  
  927. Wenn man erreichen will, daß nicht bei jedem Programmaufruf mit CallModule
  928. das Programm bzw. die Module erneut geladen werden, kann man sie mit der
  929. Funktion LoadModule aus Loader einmal laden. Sie bleiben dann so lange im
  930. Speicher, bis UnLoadModule aufgerufen wird oder das Programm endet, das
  931. das Modul Loader importierte (z.B. die Shell).
  932.  
  933. Ein gestartetes Modul kann mit SetChain aus Loader selbst bestimmen, daß
  934. nach dem eigenen Ablauf nicht zum Aufrufer zurückgekehrt sondern erstmal
  935. ein anderes Programm gestartet wird. Dies Nachstarten kann aber nur von
  936. ungelinkten Modulen aus geschehen - nach dem Ablauf eines eigenständigen
  937. Programms ist ja der Loader des MOS nicht mehr aktiv.
  938. 5.2 Bibliothek: Programme, Module und Prozesse                         5 - 20
  939. ________________________________________________________
  940.  
  941.  
  942. Es gibt Anwendungen, bei denen es darauf ankommt,  ein  Programm  nach~
  943. träglich und dauerhaft einzubinden. Dies kommt meist vor bei "Treibern" (z.B.
  944. RAMdisk-Programme)  und  Monitoren  (Programme,  die  z.B.  über  andere
  945. Prozesse  wachen).  Solche  Programme  installieren  Funktionen  auf  Vektoren
  946. bzw. Prozedurvariablen,  die  von  dem  Programm,  in  das  sie  sich  einlinken,
  947. exportiert werden. Im MOS gibt es viele Möglichkeiten für solche Programme,
  948. z.B.  können  über  die  Treibervariablen  in  FileBase  oder  TermBase  andere
  949. Ein-/Ausgabefunktionen   eingebunden   oder   kurzzeitig   Konfigurationen   in
  950. MOSConfig geändert werden.
  951.  
  952. Beispielsweise  soll  erreicht  werden,  daß  alle  Module,  die  der  Loader  lädt,
  953. angezeigt  werden.  Dazu  exportiert  das  Modul  Loader  die  Prozedurvariable
  954. Loading,  die  bei  jedem  Modulladen  aufgerufen  wird.  Es  gibt  nun  zwei
  955. Möglichkeiten. Entweder erweitert man die Shell um eine Funktion, die auf die
  956. Loader-Variable  zugewiesen  wird  und  die  Ausgabe  der  geladenen  Module
  957. durchführt. Will man aber sich die Änderung in der Shell ersparen, muß man
  958. ein kleines Programm erstellen, das dies übernimmt. Die Ausgabefunktion darf
  959. aber nur so lange auf Loading zugewiesen sein, wie das Modul im Speicher
  960. steht. Will man zurück in die Shell, um Module zu starten, damit die Funktion
  961. sie  anzeigen  kann,  endet  aber  das  Programm  und  wird  wieder  aus  dem
  962. Speicher entfernt.
  963.  
  964. Die Lösung bietet die Funktion InstallModule aus ModCtrl. Sie bewirkt, daß das
  965. Modul, das die Funktion aufruft, mitsamt seiner importierten Module resident
  966. im Speicher bleibt, bis ModCtrl selbst aus dem Speicher verschwindet (also
  967. wenn z.B. die Shell abläuft).
  968.  
  969. Wenn  also  das  Modul  vor  dem  Zuweisen  der  Loading-Variable  erst
  970. InstallModule aufruft und dann der Prozeß beendet wird, bleibt die Ausgabe~
  971. prozedur weiterhin aufrufbar.
  972.  
  973. Damit das Modul sich auch wieder freigeben und die Ausgabefunktion abmelden
  974. kann, gibt es die Möglichkeit, ein  solches  Modul  erneut  per  CallModule  zu
  975. starten. Das Modul kann dann mit FirstModuleStart (aus ModCtrl) erfragen, ob
  976. dies der erste Aufruf des Moduls ist, um so zu ermitteln, ob das Modul schon
  977. resident  war.  Ist  dies  der  Fall,  gibt  es  sich  einfach  wieder  frei  (mit
  978. ReleaseModule).
  979. 5.2 Bibliothek: Programme, Module und Prozesse                         5 - 21
  980. ________________________________________________________
  981.  
  982.  
  983. Hier das vollständige Beispielprogramm:
  984.  
  985.     MODULE ShowMods;
  986.  
  987.     FROM  SYSTEM  IMPORT  ADDRESS,  ADR;  IMPORT  ModCtrl,  Loader,
  988.        AESForms, Strings, MOSGlob;
  989.  
  990.     VAR workSpace: MemArea; oldLoading: Loader.LoadingProc;
  991.  
  992.     PROCEDURE  remove;
  993.       BEGIN
  994.         (* Wiederherstellen des alten Wertes: *)
  995.         Loader.Loading:= oldLoading;
  996.       END remove;
  997.  
  998.     PROCEDURE show ( modName, fileName: ARRAY OF CHAR;
  999.                          codeAddr: ADDRESS; codeLen: LONGCARD;
  1000.                          varAddr: ADDRESS; varLen: LONGCARD );
  1001.       VAR s: Strings.String; ok: BOOLEAN; button: CARDINAL;
  1002.       BEGIN
  1003.         (* Hier wird jedes geladene Modul ausgegeben *)
  1004.         Strings.Concat (' 0  Lade ', fileName, s, ok);
  1005.         Strings.Append (s, '   OK  ', ok);
  1006.         AESForms.FormAlert (1, s, button);
  1007.           (* GEM ist bereits durch die Shell initialisiert *)
  1008.       END show;
  1009.  
  1010.     BEGIN
  1011.       IF ModCtrl.FirstModuleStart () THEN
  1012.         (* Beim 1.Start wird die Ausgabefunktion eingerichtet. *)
  1013.         workSpace.bottom:= NIL; (* der normale Stack reicht aus*)
  1014.         ModCtrl.InstallModule (remove, workSpace);
  1015.         oldLoading:= Loader.Loading; (* Retten des alten Wertes *)
  1016.         Loader.Loading:= show     (* Zuweisen der neuen Prozedur *)
  1017.       ELSE
  1018.         (* Beim wiederholten Start wird alles entfernt. *)
  1019.         remove;  (* Wiederherstellen des alten 'Loading'-Wertes *)
  1020.         ModCtrl.ReleaseModule
  1021.       END
  1022.     END ShowMods.
  1023.  
  1024.  
  1025. Im UTILITY-Ordner befindet sich ein entsprechendes Modul ModTrace.
  1026. 5.2 Bibliothek: Programme, Module und Prozesse                         5 - 22
  1027. ________________________________________________________
  1028.  
  1029.  
  1030. Modul- und Prozeßkontrolle
  1031.  
  1032. Es gibt Anwendungen, die nicht einfach ohne weiteres beendet werden dürfen,
  1033. sondern  bei  denen  Einstellungen,  die  während  eines  Prozesses  verändert
  1034. wurden, wieder rückgängig gemacht werden müssen. Werden z.B. Interrupts
  1035. verwendet, dürfen die Interruptvektoren nach Prozeßende nicht "in die Wüste"
  1036. zeigen, weil sonst ein Systemabsturz möglich wäre. Da es möglich ist, daß ein
  1037. Prozeß unbeabsichtigt, z.B. durch einen Fehler, beendet wird, kann mit der
  1038. Funktion CatchProcessTerm aus PrgCtrl eine Prozedur installiert werden, die
  1039. automatisch   bei   Beendigung   des   eigenen   Prozesses   aufgerufen   wird.
  1040. Genaugenommen wird die Prozedur dann ausgeführt, wenn der Prozeß endet,
  1041. in  dem  der  CatchProcessTerm-Aufruf  erfolgte.  Werden  mehrere  solcher
  1042. Prozeduren während eines Prozesses angemeldet, werden sie beim Prozeßende
  1043. in entgegengesetzter Anmeldungsreihenfolge aufgerufen (letztes zuerst).
  1044.  
  1045. Module wie Files oder Storage sorgen automatisch dafür, daß offen gebliebene
  1046. Dateien oder belegter Speicher freigegeben wird, wenn der Prozeß beendet
  1047. wird, unter dem die Dateien geöffnet oder der Speicher angefordert wurde.
  1048. Damit  solche  Funktionen  über  Beginn  und  Ende  eines  Prozesses  Bescheid
  1049. wissen, gibt es im Modul PrgCtrl die Funktion SetEnvelope zur Anmeldung einer
  1050. Prozedur, die bei Prozeßbeginn und -ende aufgerufen wird.
  1051.  
  1052. Im  Files-Modul  wird  beispielsweise  eine  globale  Variable,  die  das  aktuelle
  1053. Prozeßlevel bestimmt, verwaltet. Sie wird mit Hilfe der SetEnvelope-Funktion
  1054. bei jedem Prozeßbeginn erhöht und bei jedem Prozeßende wieder verringert.
  1055. Die Files.Open-Funktion merkt sich nun für jede geöffnete Datei den Wert des
  1056. Prozeßlevels. Bei Prozeßende wird, bevor das Prozeßlevel heruntergesetzt wird,
  1057. erst  jede  offene  Datei  geschlossen,  die  unter  dem  gerade  zu  beendenden
  1058. Prozeßlevel eröffnet wurde.
  1059.  
  1060. Werden  Module  erstellt,  die  Resourcen  (z.B.  Listen,  Speicher,  Dateien)
  1061. verwalten können oder selber Resourcen anlegen oder globale Vektoren (z.B.
  1062. Interrupts  oder  TRAPs)  oder  andere  globale  Einstellungen  vornehmen,  und
  1063. sollen diese Module auch in Programmen verwendet werden können, die sich
  1064. speicher-resident  machen  (mit   InstallModule),   darf   zum   automatischen
  1065. Schließen bei Programmende nicht CatchProcessTerm, sondern CatchRemoval
  1066. aus  SysCtrl  verwendet  werden!  Siehe  dazu  auch  die  Definitionstexte  von
  1067. PrgCtrl,  SysCtrl,  ResourceHandler  sowie  das  Demo-Modul  SysLibDemo  im
  1068. DEMO-Ordner.
  1069. 5.2 Bibliothek: Programme, Module und Prozesse                         5 - 23
  1070. ________________________________________________________
  1071.  
  1072.  
  1073. Programm- und Prozeßinformationen, Base Page und Argumentzeile
  1074.  
  1075. Um zu erfahren, welche Module bei einem  Programmstart  geladen  werden,
  1076. wurde bereits die Verwendung der Funktion Loading weiter oben beschrieben.
  1077. Um die Informationen über die augenblicklich geladenen Module zu erhalten,
  1078. gibt es in ModCtrl die Funktion ModQuery. Ihr wird eine Prozedur übergeben,
  1079. die wiederholt mit den Informationen über alle im Speicher befindlichen Module
  1080. aufgerufen  wird.  Ein  Beispielprogramm  namens  ModList  befindet  sich  im
  1081. DEMO-Ordner.
  1082.  
  1083. Wenn man mit einem Debugger oder Maschinensprachemonitor von CallModule
  1084. gestartete  Prozesse  tracen  (schrittweise  verfolgen)  möchte,  kann  man  die
  1085. Loader-Variable Monitor auf eine Prozedur zuweisen, die das Monitorprogramm
  1086. oder den Debugger aktiviert. Die Monitor-Prozedur wird immer direkt vor dem
  1087. Aufruf des von CallModule zu startenden Moduls ausgeführt. Die Behandlung
  1088. der Monitor-Variablen kann in derselben Weise wie bei dem Beispielprogramm
  1089. für die Loading-Variable (s.o.) geschehen. Ein Beispielprogramm Monitor wird
  1090. mitgeliefert (UTILITY-Ordner).
  1091.  
  1092. Den Zeiger auf die Basepage jedes Prozesses erhält man mit der Funktion
  1093. GetBasePageAddr aus PrgCtrl. Für den Normalanwender ist daraus  nur  die
  1094. Argumentzeile interessant, die bei CallModule angegeben oder beim Start eines
  1095. Programms von der Shell bestimmt werden kann. Für den Zugriff darauf bietet
  1096. sich jedoch besser das Modul ArgCV an. Der Aufruf der dortigen Prozedur
  1097. InitArgCV  löst  die  Argumentzeile  gleich  in  einzelne  Argumente  auf,  und
  1098. ArgCVIO erlaubt es zusätzlich, die Ein-/Ausgaben über InOut umzuleiten, falls
  1099. das Programm als TTP-Anwendung vom Desktop gestartet werden soll: Um
  1100. z.B. die Eingabe von  der  Datei  "BATCH.TXT"  zu  ermöglichen,  kann  in  der
  1101. Argumentzeile "<BATCH.TXT" angegeben werden. Für Ausgabeumleitung kann
  1102. ">" oder ">>" verwendet werden: ">" bestimmt eine neue Datei, während ">>"
  1103. das Anfügen an eine bestehende Datei ermöglicht. Soll die Umlenkung auch
  1104. schon vom aufrufenden Programm (z.B. Command-Shell) möglich sein, muß das
  1105. Console-Modul, z.B. durch den InOut-Treiber GEMDOSIO, verwendet werden.
  1106. Der Desktop (und z.Zt. auch die Megamax-Shell)  prüfen  die  Argumentzeile
  1107. nicht auf Umlenkungsanweisungen und deshalb ist es hier  ggf.  erforderlich,
  1108. ArgCVIO zu verwenden.
  1109.  
  1110. Mit  Accessory  aus  PrgCtrl  kann  ermittelt  werden,  ob  ein  Programm  als
  1111. Accessory (mit Suffix ".ACC") gestartet wurde.
  1112.  
  1113. Das Modul MOSCtrl ist für den Normalanwender tabu. Es stellt die grund~
  1114. legenden Funktionen und Daten für die  MOS-Prozeßkontrolle  zur  Verfügung
  1115. und ist nur für die MOS-internen Module bestimmt.
  1116. 5.2 Bibliothek: Programme, Module und  Leerseiten                       5 - 24
  1117. ________________________________________________________
  1118. 5.3 Bibliothek: Laufzeitfehler-Behandlung                                  5 - 25
  1119. ________________________________________________________
  1120.  
  1121.  
  1122. 5.3  Laufzeitfehler-Behandlung
  1123.  
  1124.  
  1125. Was sind Laufzeitfehler ?
  1126.  
  1127. Laufzeitfehler können unter mehreren Umständen eintreten. Z. B. kann eine
  1128. Variable einen ungültigen Wert erhalten, eine Division durch Null erfolgen oder
  1129. ein Pointerzugriff mit einem uninitialisierten Pointer durchgeführt werden.
  1130.  
  1131. Nun ist es in den meisten Fällen zu aufwendig, solchen Fehlern programm~
  1132. technisch zuvorzukommen. Man müßte z. B. vor jeder Berechnung mit Zahlen
  1133. prüfen, ob die Ergebnisse nicht ungültig werden. Statt dessen können solche
  1134. Prüfungen automatisch vom Mikroprozessor und vom Code, den der Compiler
  1135. erzeugt, vorgenommen werden. Der Vorteil liegt darin, daß der Programmierer
  1136. sich nicht selbst um die vielfältigen Prüfungen kümmern muß. Der Nachteil ist,
  1137. daß die vom Prozessor oder vom Spezialcode des Compilers erkannten Fehler
  1138. alle eine Standard-Fehlerbehandlung durchlaufen, anstatt individuell behandelt zu
  1139. werden.
  1140.  
  1141. Aus diesem Grund ist es nötig, sich beim Programmieren Gedanken darüber zu
  1142. machen, ob absehbar mögliche Fehler vorher erkannt werden sollen, um darauf
  1143. dann direkt zu reagieren, oder ob es ausreicht, nach einer Berechnung etc. zu
  1144. erkennen, daß überhaupt ein Fehler aufgetreten war.
  1145.  
  1146. Dazu ein Beipiel. Folgende Berechnung sei durchzuführen:
  1147.  
  1148.   lösung:= a * b + c DIV ( d * e );
  1149.  
  1150. Wenn  die  Variablen  a  bis  e  alle  möglichen  Werte  annehmen  können,  sind
  1151. mehrere Fehler möglich:
  1152.  
  1153.   - Ein Überlauf tritt bei der Multiplikation von a * b auf.
  1154.   - Ein Überlauf tritt bei der Multiplikation von d * e auf.
  1155.   - Ein Überlauf tritt bei der Addition von d * e und c DIV d * e auf.
  1156.   - Eine Division durch Null tritt auf, weil d oder e Null ist.
  1157.  
  1158. Wenn es darauf ankommt, herauszufinden, welche Variable einen illegalen Wert
  1159. hat, muß dies in aufwendiger Weise vor der Berechnung geprüft werden. Ist
  1160. dagegen  nur  wichtig,  zu  erfahren,  ob  überhaupt  ein  gültige  Lösung  dabei
  1161. entsteht, reicht es aus, die automatische Fehlererkennung darüber wachen zu
  1162. lassen.
  1163.  
  1164. Die  automatische  Fehlererkennung  liefert  lediglich  die  Information,  daß  ein
  1165. Fehler auftrat und was der Anlaß für den Fehler war. Für das Beispiel oben
  1166. wird  im  Fehlerfalle  nur  übermittelt,  daß  entweder  ein  Überlauf  oder  eine
  1167. Division durch Null den Fehler auslöste.
  1168. 5.3 Bibliothek: Laufzeitfehler-Behandlung                                  5 - 26
  1169. ________________________________________________________
  1170.  
  1171.  
  1172. Fehlergruppen
  1173.  
  1174. Laufzeitfehler kann man in vier Gruppen (Ursachen) aufteilen:
  1175.  
  1176.   - Exceptions: Dies sind Fehler, die der Mikroprozessor erkennt,  z.  B.  16
  1177.     Bit-Division durch Null oder Zugriff auf nicht vorhandenen Speicherbereich.
  1178.     Der  Prozessor  hat  dafür  an  festen  Systemadressen  Sprungvektoren
  1179.     vorgesehen, die in einem solchen Fehlerfalle angesprungen werden. Es ist
  1180.     nicht  möglich,  die  Erkennung  der  Fehler  durch  den  Prozessor  zu
  1181.     unterbinden.
  1182.  
  1183.   - Soft-Fehler:  Dazu  zählen  alle  Fehler,  die  durch  extra  programmierte
  1184.     Abfragen  erkannt  werden.  Solche  Abfragen  werden  z.B.  vom  Compiler
  1185.     erzeugt (wenn nicht die Option (*$R-*) eingestellt ist) und stehen auch in
  1186.     vielen  der  mitgelieferten  Library-Module.  Sie  werden  alle  über  eine
  1187.     erzwungene Exception-Auslösung gemeldet.
  1188.  
  1189.   - Raise-Funktionen: Damit können Sie selbst Fehlermeldungen auslösen. Dies
  1190.     ist  z.  B.  sinnvoll,  wenn  Sie  ein  Modul  mit  mathematischen  Funktionen
  1191.     programmieren. Dann können Sie selbst Fehlerabfragen durchführen  und
  1192.     ggf. die Funktion RaiseError aus dem Modul ErrBase aufrufen, um einen
  1193.     normalen Laufzeitfehler zu simulieren.
  1194.  
  1195.   - Dateifehler: Das Dateisystem des MOS prüft in vielen Fällen nach, ob Sie
  1196.     einen vorher aufgetretenen Fehler, z. B. einen Lesefehler, erkannt haben.
  1197.     Ist dies nicht der Fall, wird eine Fehlermeldung ausgelöst.
  1198.  
  1199. Die ersten drei Gruppen können, da sie alle gleichartige Fehler melden, von
  1200. einer einzigen Funktion behandelt werden. Sie werden im Folgenden "allgemeine
  1201. Laufzeitfehler" genannt. Die Dateifehler treten unter anderen Umständen auf
  1202. und müssen auch anders behandelt werden.
  1203.  
  1204. Darüber hinaus faßt das Modul EasyExceptions alle diese Fehler zusammen und
  1205. ermöglicht auf eine höheren Ebene eine  sehr  komfortable  Fehlerbehandlung.
  1206. Dazu mehr am Ende dieses Kapitels.
  1207. 5.3 Bibliothek: Laufzeitfehler-Behandlung                                  5 - 27
  1208. ________________________________________________________
  1209.  
  1210.  
  1211. Allgemeine Laufzeitfehler
  1212.  
  1213. Die Fehler der ersten  beiden  Gruppen  (s.o.)  werden  auf  dem  selben  Weg
  1214. gemeldet: über Exceptions. Mit dem Modul Excepts können diese und auch alle
  1215. anderen Exceptions abgefangen werden. (Tritt eine Exception auf, die nicht
  1216. abgefangen wird, blitzen nur kurz ein paar häßliche Bomben auf dem Atari-
  1217. Bildschirm auf.) Das Modul bietet die Funktion InstallExc, mit der eine Prozedur
  1218. angemeldet werden kann, die bei Eintritt einer der anzugebenden Exceptions
  1219. aufgerufen  wird.  Wird  bei  einer  Exception  die  Prozedur  dann  aufgerufen,
  1220. bekommt sie Werte aller Prozessorregister vor der Exception übergeben. Sie
  1221. kann dann entscheiden, ob sie selbst reagieren will. Wenn ja, kann sie z. B.
  1222. eine Fehlermeldung anzeigen. Danach kann sie die Prozessorregister ändern
  1223. und mit RETURN FALSE erreichen, daß die Prozessorregister zurückgeladen
  1224. werden und das unterbrochene Programm fortgeführt wird. Wenn sie  nicht
  1225. reagieren will, kehrt sie mit RETURN TRUE zurück, und es wird vom Modul
  1226. Excepts  die  Prozedur  aufgerufen,  die  vor  dem  InstallExc-Aufruf  für  die
  1227. Exception angemeldet war. Diese Prozedur kann dann genauso verfahren.
  1228.  
  1229. Mit der Prozedur RaiseExc aus Excepts können Sie eine Exception an  der
  1230. Stelle simulieren, von der der Aufruf geschieht.
  1231.  
  1232. Wird das Modul ErrBase eingebunden, ruft es automatisch InstallExc auf und
  1233. fängt alle Exceptions, die von Modula-Programmen ausgelöst werden können,
  1234. ab. Es exportiert eine Prozedurvariable, die bei einer solchen Exception oder
  1235. bei Aufruf der dortigen Funktion RaiseError aufgerufen wird. Von Anwender~
  1236. programmen sollte diese globale Variable aber in der Regel nicht verwendet
  1237. werden, um Fehler abzufangen.
  1238.  
  1239. Statt dessen gibt es  noch  ein  weiteres  Modul,  HdlError,  das  eine  interne
  1240. Prozedur auf die Prozedurvariable aus ErrBase zuweist. Dieses Modul bietet
  1241. nun die komfortablen Funktionen zum Abfangen und Behandeln der allgemeinen
  1242. Laufzeitfehler.
  1243.  
  1244. CatchErrors aus HdlError erlaubt es, Prozeduren anzumelden, die bei jedem
  1245. allg.  Laufzeitfehler  aufgerufen  werden.  Die  Prozedur  bekommt  bei  einem
  1246. Laufzeitfehler  die  Fehlernummer  (alle  Fehlernummern  sind  in  MOSGlobals
  1247. definiert  und  erklärt),  einen  optionalen  Text,  die  Prozessordaten  von  der
  1248. Exception, die Information, ob das Programm noch fortgeführt werden kann,
  1249. und  die  Angabe,  ob  die  fehlerauslösende  Routine  oder  ihr  Aufrufer  als
  1250. Verursacher  gilt.  Der  Text  kann  v.  A.  bei  RaiseError  als  zusätzliche
  1251. Information  neben  der  Fehlernummer  übergeben  werden.  Bei  vom  Compiler
  1252. erzeugten Fehlermeldungen oder bei Exceptions ist der Text immer leer. Wird
  1253. die Prozedur aufgerufen, hat sie in der Regel drei Möglichkeiten:
  1254. 5.3 Bibliothek: Laufzeitfehler-Behandlung                                  5 - 28
  1255. ________________________________________________________
  1256.  
  1257.  
  1258.   - Sie will den Fehler nicht speziell behandeln. Dann verläßt sie die Funktion
  1259.     mit  RETURN  TRUE.  Waren  noch  weitere,  ältere  CatchErrors-Aufrufe
  1260.     erfolgt,  werden  nun  deren  angemeldete  Prozeduren  in  gleicher  Weise
  1261.     aufgerufen. Ist keine weitere 'call'-Funktion vorhanden, wird das Programm
  1262.     mit der Fehlernummer als "Exitcode" (siehe PrgCtrl.TermProcess) beendet.
  1263.  
  1264.   - Sie hat den Fehler behandelt und möchte erreichen, daß das Programm
  1265.     hinter der Fehlerauslösung fortfahren kann. Dazu muß sie die Funktion mit
  1266.     FALSE verlassen. Dies sollte in der Regel  nur  getan  werden,  wenn  es
  1267.     durch eines der Argumente, die der Prozedur übergeben wurden, erlaubt
  1268.     wird. Vorsicht: Bei Busfehlern und Adreßfehlern kann das Programm nicht
  1269.     ohne Änderung der Prozessorregister fortfahren !
  1270.  
  1271.   - Der Fehler wurde erkannt, und das Programm soll abgebrochen werden.
  1272.     Dann ist TermProcess aus PrgCtrl aufzurufen.
  1273.  
  1274. Diese Wahlmöglichkeit hat nun riesige Vorteile. Stellen Sie sich vor, Sie haben
  1275. eine Prozedur, die eine Berechnung durchführt. Sie soll ein Ergebnis liefern,
  1276. das anzeigt,  ob  die  Berechnung  fehlerfrei  verlief.  Da  nun  damit  gerechnet
  1277. werden  muß,  daß  darin  ein  Laufzeitfehler  auftreten  kann,  wird  vor  der
  1278. Berechnung mit CatchErrors eine Hilfsfunktion installiert. Tritt danach irgendein
  1279. Fehler auf, wird die Funktion als erstes aufgerufen, und sie kann entscheiden,
  1280. ob der Fehler in der Berechnung entstanden oder ein ganz anderer Fehler ist.
  1281. Je nachdem setzt sie ein Fehlerflag und läßt die Berechnung zu Ende laufen,
  1282. oder sie läßt den außerordentlichen Fehler von der zuvor installierten Fehler~
  1283. behandlung  bearbeiten  (dies  führt  dann  normalerweise  zum  Anzeigen  des
  1284. Fehlers von der Standard-Fehlerbehandlung der Shell/GEMError).
  1285. 5.3 Bibliothek: Laufzeitfehler-Behandlung                                  5 - 29
  1286. ________________________________________________________
  1287.  
  1288.  
  1289. Hier ein Bespielprogramm:
  1290.  
  1291.     VAR fehlerAufgetreten: BOOLEAN;
  1292.  
  1293.     PROCEDURE fehler (     nummer       : INTEGER;
  1294.                                 text         : ARRAY OF CHAR;
  1295.                                 verursacher: ErrBase.ErrResp;
  1296.                                 abbruch     : RtnCond,
  1297.                            VAR excDaten    : Excepts.ExcDesc ): BOOLEAN;
  1298.       BEGIN
  1299.         IF nummer = MOSGlob.DivByZero THEN
  1300.           fehlerAufgetreten:= TRUE;
  1301.           RETURN FALSE  (* -> Programm fortführen *)
  1302.         ELSE
  1303.           RETURN TRUE   (* -> Fehlermeldung weiterleiten *)
  1304.         END
  1305.       END fehler;
  1306.  
  1307.     PROCEDURE modulo ( a,b: CARDINAL; VAR c: CARDINAL; VAR ok: BOOLEAN );
  1308.         (* Berechnet den Modulo-Wert v. 'a' und 'b' und liefert die *)
  1309.         (* Lösung in 'c'. Bei einen Fehler ('b'=0) ist 'ok' FALSE,  *)
  1310.         (* sonst TRUE.                                                          *)
  1311.       VAR stack: ARRAY  1..1000  OF CARDINAL; (* 2 KB Stack reichen *)
  1312.            wsp: MOSGlob.MemArea;
  1313.       BEGIN
  1314.         fehlerAufgetreten:= FALSE;
  1315.         wsp.bottom:= ADR ( stack );
  1316.         wsp.length:= SIZE ( stack );
  1317.         CatchErrors ( fehler, wsp );       (* Fehlerroutine anmelden *)
  1318.         (* Jetzt kann gerechnet werden: *)
  1319.         c:= a - (a DIV b) * b;
  1320.         (* Das reicht. *)
  1321.         ReleaseCatcher ( fehler );         (* Fehlerroutine abmelden *)
  1322.         ok:= NOT fehlerAufgetreten
  1323.       END modulo;
  1324.  
  1325. In diesem Beispielprogramm wäre es natürlich einfacher und schneller, b mit
  1326. Null  zu  vergleichen.  Erst  in  komplexeren  Berechnungen  lohnt  sich  das
  1327. Verfahren. Aber mathematische Berechnungen sind nicht das einzige, bei dem
  1328. Fehler in dieser Weise vorteilhaft abgefangen werden können.
  1329. 5.3 Bibliothek: Laufzeitfehler-Behandlung                                  5 - 30
  1330. ________________________________________________________
  1331.  
  1332.  
  1333. Wenn nach dem Erkennen des Laufzeitfehlers im obigen Beispiel die fehlerher~
  1334. vorrufende Routine nicht weiter ausgeführt werden darf, sondern gleich aus
  1335. modulo zurückgekehrt werden soll, kann die Funktion so abgeändert werden,
  1336. daß die Berechnung selbst in einer Unterfunktion durchgeführt und diese dann
  1337. mit CallProcess aus ModCtrl aufgerufen wird. In fehler muß dann TermProcess
  1338. mit einem Wert ungleich Null statt "RETURN FALSE" aufgerufen werden. Statt
  1339. über die globale Variable fehlerAufgetreten kann dann über den exitCode von
  1340. CallProcess ein aufgetretener Fehler erkannt werden.
  1341.  
  1342. Genauso bietet sich CatchErrors an, wenn einfach verhindert werden soll, daß
  1343. Laufzeitfehler  an  den  Anwender  mit  einer  Bildschirmmeldung  gelangen  und
  1344. dadurch das Programm unterbrochen wird. Bei Berechnungen mit CARDINAL-
  1345. und INTEGER-Werten reicht es in der Regel, dem Compiler durch die Option
  1346. (*$R-*) im Quelltext mitzuteilen, keine Prüfungen vorzunehmen. Aber z. B. bei
  1347. Benutzung von REAL-Werten werden vorcompilierte Funktionen aus dem Modul
  1348. Runtime  importiert,  die  immer  Fehlerprüfungen  vornehmen.  Hier  kann  im
  1349. Zweifelsfall nur mit CatchErrors sichergestellt werden, daß das Programm die
  1350. Kontrolle behält.
  1351.  
  1352. Ein weiteres Beispiel für die Fehlerbehandlung von Laufzeitfehlern ist das Modul
  1353. GEMError,  das  Sie  als  Quelltext  erhalten  haben.  Es  ist  z.B.  in  die  Shell
  1354. eingebunden und fängt als letztes Modul alle Fehler ab und zeigt sie an. Ein
  1355. gelinktes  Programm  sollte  immer  in  irgendeiner  Weise  evtl.  auftretende
  1356. Laufzeitfehler abfangen. Am einfachsten ist es, dazu GEMError einzubinden,
  1357. was normalerweise auch geschieht.
  1358.  
  1359.  
  1360. Dateifehler
  1361.  
  1362. Im Kapitel über das Dateisystem wird beschrieben, wie es dazu kommen kann,
  1363. daß eine  Fehlermeldung  für  Dateifehler  ausgelöst  werden  kann.  Das  Modul
  1364. FileBase enthält die Prozedurvariable HandleError, die aufgerufen wird, wenn
  1365. ein Dateifehler gemeldet werden soll. Wenn sie unverändert bleibt, werden alle
  1366. Dateifehlermeldungen ignoriert.
  1367.  
  1368. Das Modul GEMError weist auf HandleError eine Routine zu, die den Fehler
  1369. anzeigt, dem Anwender bei einem Fehler über den Grund und die Programm~
  1370. stelle informiert und ihm die Möglichkeit bietet, das Programm zu beenden,
  1371. fortzuführen oder den  Editor  aufzurufen,  um  die  Fehlerposition  anzuzeigen.
  1372. Dazu wird von HandleError die Dateifehlernummer  und  die  Dateivariable,  in
  1373. deren Datei der Fehler auftrat, übergeben. Zusätzlich wird noch ein Argument
  1374. übergeben, das die Adresse der Prozedur  im  Speicher  angibt,  an  der  der
  1375. Dateifehler erkannt wurde.
  1376. 5.3 Bibliothek: Laufzeitfehler-Behandlung                                  5 - 31
  1377. ________________________________________________________
  1378.  
  1379.  
  1380. In FileBase findet sich außerdem die Prozedurvariable CloseFile. Sie wird bei
  1381. Programm-/Prozeßende für jede unter dem Prozeß eröffnete und noch offen
  1382. gebliebene  Datei  aufgerufen.  Wird  sie  nicht  verändert,  wird  jede  offen
  1383. gebliebene Datei automatisch geschlossen. GEMError zeigt jedoch alle offenen
  1384. Dateien an und bietet die Möglichkeit, Disk-Dateien, die mit Create angelegt
  1385. wurden, zu löschen. Dies ist von Vorteil, wenn ein Programm, das eine Datei
  1386. erzeugt, durch einen Laufzeitfehler beendet wird. Oft ist dann die erzeugte
  1387. Datei unvollständig und kann gelöscht werden.
  1388.  
  1389.  
  1390. Fehlerbehandlung mit dem Modul EasyExceptions
  1391.  
  1392. Dieses  Modul  ermöglicht  nicht  nur  die  Abfrage  von  Laufzeitfehlern,  eigene
  1393. Fehler können auf einfache Weise selbst ausgelöst werden, und die Funktion, in
  1394. der der Fehler auftrat, kann auf bequeme Weise wieder verlassen werden.
  1395.  
  1396. Kernstück der Fehlerkontrolle ist die Funktion Call. Als erstes Argument erhält
  1397. sie die Prozedur, die die eigentliche Operation durchführen soll. Call nimmt alle
  1398. notwendigen Installationen für die Fehlerabfrage vor (über HdlError.CatchErrors)
  1399. und  sieht  außerdem  einen  zentralen  Rücksprung  für  alle  Fehler  vor.  Dann
  1400. startet Call die eigentliche Prozedur. Kehrt die Prozedur ohne Fehler zurück,
  1401. liefert Call einen Wert, der den fehlerfreien Ablauf anzeigt. Tritt dagegen ein
  1402. Fehler  auf,  wird  die  Prozedur  sofort  abgebrochen  und  Call  liefert  einen
  1403. Fehlerwert.
  1404.  
  1405. Die  Fehler  können  nicht  nur  durch  die  bereits  erwähnten  Möglichkeiten
  1406. (RaiseError, CPU-Exception, Soft-Error, Dateifehler), sondern auch über die
  1407. Raise-Funktion aus EasyExceptions gemeldet werden. Die Raise-Funktion hat
  1408. einen  entscheidenden  Vorteil  gegenüber  RaiseError:  Sie  erhält  nicht  eine
  1409. INTEGER-Zahl, die vorher festgelegt werden muß, sondern einen opaque-Wert,
  1410. welcher vorher über die Funktion New des Moduls angefordert werden muß.
  1411. So können mehrere Funktionen unabhängig voneinander  eigene  Fehler-Werte
  1412. mit New anfordern. Damit ist gewährleistet, daß es keine Überschneidungen
  1413. bei  den  Werten  gibt.  Die  Module,  die  eigene  Fehler  über  Raise  auslösen
  1414. können,  müssen  lediglich  Variablen  oder  Funktionen  exportieren,  die  die
  1415. angeforderten Werte liefern, damit ein Vergleich möglich ist.
  1416.  
  1417. Ein Beispielmodul für die Anwendung von EasyExceptions findet sich im DEMO-
  1418. Ordner unter dem Namen EXCTEST.M.
  1419. 5.3 Bibliothek: Laufzeitfehler-Behandlung                                  5 - 32
  1420. ________________________________________________________
  1421.  
  1422.  
  1423. Fehlerbehandlung in Accessories
  1424.  
  1425. Gerade Accessories sollten auf mögliche oder auch unerwartete Laufzeitfehler
  1426. vorbereitet sein: Sollte ein Accessory tatsächlich einmal unkontrolliert  einen
  1427. Laufzeitfehler auslösen, ist der Atari aufgrund der dürftigen Konzeption seiner
  1428. Accessory-Verwaltung zum Stillstand verurteilt: Nichts geht mehr.
  1429.  
  1430. Also überlegen Sie es sich gut: Wenn Sie ein Accessory programmieren und
  1431. dies einen Fehler macht, wenn Sie gerade in der Hauptanwendung, z.B. einer
  1432. Textverarbeitung, richtig viele Daten eingegeben haben, ist es doch sicher sehr
  1433. ärgerlich, daß Ihre Daten nicht wegen einem Fehler in der Textverarbeitung,
  1434. sondern  wegen  einem   eigentlich   unbeteiligten   Programm   das   Nirwana
  1435. aufgesucht haben, oder?
  1436.  
  1437. Da  Sie  ein  vorsichtiger  Mensch  sind  -  schließlich  haben  Sie  sich  ja  für
  1438. Modula-2 und nicht für C entschieden, freut es Sie natürlich besonders, daß
  1439. wir Sie auch hier nicht im Stich lassen: Verwenden Sie einfach die Funktion
  1440. Call aus EasyExceptions, wie dies z.B. im DEMO-Modul AccDemo gezeigt wird.
  1441. Die Funktionen aus HdlError können Sie hier nicht benutzen - sie haben in
  1442. Accessories ohne weiteres keine Wirkung.
  1443. 5.4 Bibliothek: Dateisystem                                               5 - 33
  1444. ________________________________________________________
  1445.  
  1446.  
  1447. 5.4  Dateisystem
  1448.  
  1449. Das Dateisystem ermöglicht Ein-/Ausgaben von Texten und anderen Daten auf
  1450. Disk (Floppies, Harddisks). Zudem läßt es Textein-/ausgaben auf "sequentielle"
  1451. Einheiten (Device, z. B. Bildschirm, Tastatur, Drucker, Midi-Schnittstelle) zu.
  1452.  
  1453. Zum Dateisystem gehören die folgenden Module:
  1454.     - Files       Öffnen und Schließen von Dateien.
  1455.     - Binary     Nicht-textuelle Ein-/Ausgabe von Daten auf Diskdateien.
  1456.     - Text       Textuelle Ein-/Ausgabe auf beliebige Dateien.
  1457.     - NumberIO  Ein-/Ausgabe von Zahlen in Textform auf beliebige Dateien.
  1458.     - InOut      Ein-/Ausgabe von Text und Zahlen auf eine Standarddatei.
  1459.  
  1460.  
  1461.  
  1462. Dateimodi
  1463.  
  1464. Es gibt zwei verschiedene Modi, um auf eine Datei zuzugreifen. Die beiden
  1465. unterscheiden sich grundsätzlich in der Absicht, was für eine Art von Daten
  1466. bearbeitet werden soll. Entweder wird beabsichtigt, nur normal lesbaren Text
  1467. ein- und auszugeben oder, es sollen Daten (ggf. incl. Text), die in der vom
  1468. Rechner verschlüsselten Form vorliegen, in einer Datei gespeichert werden.
  1469.  
  1470. Beispiel: Eine Zahl kann in zwei Formen vorliegen, entweder als String, damit
  1471. sie auf dem Bildschirm anzeigbar ist, oder als rechnerkodierter Wert, z. B. in
  1472. einer CARDINAL-Variable. Nur in der rechnerinternen Form (binär) kann mit
  1473. ihr  gerechnet  werden,  nur  die  Textform  ist  für  den  Anwender  lesbar.
  1474. Funktionen wie WriteCard wandeln die in binärer Form übergebene Zahl zur
  1475. Ausgabe erst in einen String um (für Umwandlungen von binär dargestellten
  1476. Zahlen in Strings und umgekehrt gibt es die Module Convert und StrConv).
  1477.  
  1478. Zurück zu den zwei Dateimodi. Binäre Daten zu speichern, spart Platz und
  1479. Zeit. Solche kodierten Daten dürfen aber nur in Diskdateien abgelegt, nicht
  1480. jedoch z.B. auf Bildschirm oder Drucker ausgegeben werden.
  1481.  
  1482. Soll  dagegen  ausschließlich  Text  (also  auch  Zahlen  in  Textform)  ein-  und
  1483. ausgegeben werden, ist das Medium frei wählbar.
  1484. 5.4 Bibliothek: Dateisystem                                               5 - 34
  1485. ________________________________________________________
  1486.  
  1487.  
  1488. Öffnen einer Datei
  1489.  
  1490. Um auf eine Datei zugreifen zu können, muß man einen Zugriff darauf anmel~
  1491. den. Dies kann mit Open oder Create aus Files geschehen. Dabei wird ein Na~
  1492. me übergeben, der die anzusprechende Datei bezeichnet. Der Name kann dabei
  1493. sowohl ein Disk-Dateiname sein, z. B. "A:ADRESS.DAT", als auch, wenn man
  1494. den rein textuellen Modus wählt, der Name eines sequentiellen Devices. Hierzu
  1495. gehören:
  1496.   - "CON:"  für  Bildschirmausgabe  und  Tastatureingabe  mit  gleichzeitiger
  1497.               Bildschirmanzeige (mit "Echo"),
  1498.   - "KBD:"   für Tastatureingabe ohne Echo,
  1499.   - "AUX:"   für Ein- und Ausgabe über die serielle Schnittstelle,
  1500.   - "PRN:"   für Ausgabe auf den Druckerport,
  1501.   - "MIDI:"  für Ein- und Ausgabe über den Midi-Port und
  1502.   - weitere  selbstdefinierte  Namen  für  eigene  Devices,  die  über  die  Unit-
  1503.               Variablen in FileBase konfiguriert werden können (s.u.).
  1504.  
  1505. Beim Öffnen wird außerdem der Zugriffsmodus angegeben. Für den binären
  1506. Zugriff kann writeOnly (nur Schreiben auf Datei), readOnly (nur Lesen) oder
  1507. readWrite(Lesen und Schreiben) angegeben werden. Für textuellen Zugriff ist
  1508. readSeqTxt (nur Lesen), writeSeqTxt (nur Schreiben) oder appendSeqTxt (nur
  1509. Schreiben, bei Diskdateien neue Daten an vorhandene Daten anhängen).
  1510.  
  1511. Der Unterschied zwischen Open und Create: Open öffnet stets eine vorhande~
  1512. ne Datei, während Create versucht, eine neue Datei (bei Diskzugriff) anzule~
  1513. gen. Bei Zugriff auf sequentielle Devices, die ja stets schon vorhanden sind,
  1514. sind Open und Create gleichbedeutend.
  1515.  
  1516. Create hat noch einen zusätzlichen Parameter, der bestimmt, was passieren
  1517. soll, wenn schon eine Diskdatei unter dem angegebenen Namen existiert. Ist
  1518. dieser Parameter noReplace, heißt das, daß in diesem Fall die vorhandene Datei
  1519. erhalten bleibt und ein Fehler geliefert wird. Ist dagegen replaceOld angegeben,
  1520. wird eine eventuell schon vorhandene Diskdatei gelöscht.
  1521.  
  1522. Dazu einige Anwendungsbeispiele:
  1523.  
  1524.   -  Wenn der Zugriffsmodus readOnly oder readSeqTxt ist, wird grundsätzlich
  1525.      Open verwendet.
  1526.  
  1527.   -  Wird textuell geschrieben mit dem Modus writeSeqTxt oder appendSeqTxt,
  1528.      ist meist Create zu verwenden.
  1529.  
  1530.   -  Wird eine vorhandene Diskdatei mit Open im Modus readWrite, writeOnly
  1531.      oder  writeSeqTxt  geöffnet,  überschreiben  neu  ausgegebene  Daten  die
  1532.      alten von Beginn der Datei an.
  1533. 5.4 Bibliothek: Dateisystem                                               5 - 35
  1534. ________________________________________________________
  1535.  
  1536.  
  1537. Bei Open und Close wird als erster Parameter eine Variable vom TypeFile(aus
  1538. Files) erwartet. Diese Variable wird dann von den Funktionen initialisiert und ist
  1539. bei weiteren Dateioperationen stets als erstes Argument anzugeben, um damit
  1540. die geöffnete Datei zu identifizieren. Wenn man also zwei Dateien gleichzeitig
  1541. offen haben will, muß man auch zwei Variablen vom Type File deklarieren und
  1542. je eine für jede Datei verwenden.
  1543.  
  1544.  
  1545. Ein-/Ausgabe von Daten
  1546.  
  1547. Beim Öffnen einer Diskdatei wird ein Dateizeiger angelegt, der zu Beginn auf
  1548. das erste Datum der Datei zeigt, sofern sie nicht leer ist. Ausnahme: Wenn
  1549. der Modus appendSeqTxt ist, zeigt er hinter das  Ende  der  Datei.  Werden
  1550. Daten  gelesen  oder  geschrieben,  geschieht  dies  immer  ab  der  aktuellen
  1551. Zeigerposition aufwärts, und der Zeiger wird dabei automatisch erhöht. Wird
  1552. eine Datei auf ein sequentielles Device geöffnet, werden die Textdaten alle in
  1553. Folge gelesen oder geschrieben.
  1554.  
  1555. Werden  Daten  am  Ende  einer  Diskdatei  geschrieben,  wird  die  Datei
  1556. automatisch um die erforderliche Datenmenge verlängert.
  1557.  
  1558. Für  Binärdateien  können  alle  Funktionen  aus  den  Modulen  Binary,  Text
  1559. (Ausnahme:  EOL)  und  NumberIO  verwendet  werden.  In  Binary  gibt  es
  1560. Funktionen zum Schreiben von beliebigen Daten. So schreibt z. B. WriteWord
  1561. beliebige Daten mit Word-Länge in eine Datei, z. B. CARDINAL-, INTEGER-
  1562. oder  Aufzählungstyp-Variablen.  Mit  WriteBlock  können  beliebige  Daten~
  1563. strukturen  geschrieben  werden,  z.B.  RECORDs  und  ARRAYs.  WriteBytes
  1564. erlaubt es, eine Adresse und die Länge eines Datenbereichs zum Schreiben zu
  1565. bestimmen. Ebenso gibt es passende Read...-Funktionen zum Dateilesen.
  1566.  
  1567. In Binary gibt es weiterhin die Funktion FileSize, die die aktuelle Länge einer
  1568. Datei in Bytes liefert. Die aktuelle Position des Dateizeigers kann mit FilePos
  1569. ermittelt und mit Seek neu gesetzt werden. Seek bietet sich  vor  allem  in
  1570. Kombination mit dem Zugriffsmodus readWrite an, um in einer Datei, die aus
  1571. vielen  gleichartigen,  hintereinandergereihten  Datenfeldern  besteht,  einzelne
  1572. Daten herauszugreifen oder zu  verändern.  Wenn  mit  Seek  der  Dateizeiger
  1573. hinter  das  aktuelle  Dateiende  positioniert  wird,  wird  die  Datei  automatisch
  1574. entsprechend erweitert.
  1575.  
  1576. Die Module Text und NumberIO enthalten Funktionen zur Textein-/ausgabe, wie
  1577. sie auch in InOut und Terminal vorkommen. Die Funktionen, bis auf EOL aus
  1578. Text, dürfen sowohl im  Text-  als  auch  im  Binärmodus  verwendet  werden.
  1579. Allerdings  funktioniert  die  Behandlung  des  Dateiendes  in  den  beiden  Modi
  1580. unterschiedlich.
  1581. 5.4 Bibliothek: Dateisystem                                               5 - 36
  1582. ________________________________________________________
  1583.  
  1584.  
  1585. Dateiende-Behandlung
  1586.  
  1587. Mittels der Funktion EOF  kann  ermittelt  werden,  ob  aus  einer  Datei  noch
  1588. weitere Daten gelesen werden können und ob ein Fehler aufgetreten ist.
  1589.  
  1590. Während im Textmodus nach Erreichen des Dateiendes die Dateioperationen
  1591. unbedingt beendet werden müssen (da nichts anderes mehr funktioniert), kann
  1592. im  Binärmodus,  falls  mit  writeOnly  oder  readWrite  geöffnet  wurde,  am
  1593. Dateiende geschrieben oder auch mit Seek eine andere Position in der Datei
  1594. erreicht werden.
  1595.  
  1596. Auch ist die Funktion EOF  im  Binärmodus  jederzeit  aufrufbar,  während  im
  1597. Textmodus dies nur erlaubt ist, wenn die Datei mit readSeqTxt - jedoch nicht
  1598. mit writeSeqTxt oder appendSeqTxt - geöffnet wurde.
  1599.  
  1600. Im Binärmodus zeigt EOF dann das Dateiende an, wenn der Dateizeiger genau
  1601. auf das Ende der Datei zeigt. So kann also schon vor einem Lesezugriff mit
  1602. dieser Funktion ermittelt werden, ob überhaupt noch Daten vorhanden sind.
  1603.  
  1604. Im Textmodus gibt es nicht unbedingt einen Dateizeiger, denn der existiert ja
  1605. nur bei Diskdateien, aber nicht bei sequentiellen Devices. Deshalb erfolgt hier
  1606. die  Dateiendeerkennung  auf  eine  andere  Weise,  und  zwar  mit  einem
  1607. bestimmten  Dateiendezeichen.  Die  Lesefunktionen  prüfen  jedes  gelesene
  1608. Zeichen. Ist es das Dateiendezeichen, ist automatisch das Dateiende erreicht.
  1609. Daraus folgt, daß erst ein Zeichen gelesen werden muß, bevor das Dateiende
  1610. erkannt werden kann.
  1611.  
  1612. Bei Textdateien auf Disk wird zusätzlich überprüft, ob der  Dateizeiger  das
  1613. Dateiende erreicht hat, damit es keine  Probleme  gibt,  wenn  eine  Diskdatei
  1614. gelesen wird, die kein Dateiendezeichen enthält.
  1615.  
  1616. Es gibt zwei Gruppen von Lesefunktionen, bei denen diese Unterschiede beach~
  1617. tet werden müssen. Auf der einen Seite die Read-Funktion, auf der anderen
  1618. die ReadString-Funktion und die Funktionen aus NumberIO.
  1619.  
  1620. Die Read-Funktion ist leicht durchschaubar. Im Textmodus muß nach einem
  1621. Lesezugriff geprüft werden, ob das Dateiende erreicht ist. In dem Fall ist das
  1622. gelesene Zeichen nicht mehr zu verwenden, denn es ist lediglich das Ende~
  1623. kennzeichen.
  1624.  
  1625. Bei ReadString ist der erhaltene String verwendbar, es ist lediglich das Ende~
  1626. kennzeichen nicht darin enthalten. Bei den Lesefunktionen aus NumberIO ist die
  1627. Zahl gültig, sofern deren success-Argument TRUE ist.
  1628. 5.4 Bibliothek: Dateisystem                                               5 - 37
  1629. ________________________________________________________
  1630.  
  1631.  
  1632. Als Beispiel je eine Leseschleife für den Binär- und den Textmodus:
  1633.  
  1634.   (* Für Binärdateien *)
  1635.   WHILE NOT Files.EOF (f) DO  (* EOF schon vor Zugriff bekannt *)
  1636.     Text.Read (f, ch);
  1637.     Verarbeite (ch)
  1638.   END;
  1639.  
  1640.   (* Für Textdateien *)
  1641.   LOOP
  1642.     Text.Read (f, ch);
  1643.     IF Files.EOF (f) THEN EXIT END;
  1644.                                   (* EOF wird erst nach Lesen erkannt *)
  1645.     Verarbeite (ch)          (* 'ch' nur gültig, wenn kein EOF    *)
  1646.   END;
  1647.  
  1648. Bei Dateien, die zum textuellen Lesen eröffnet sind, ist außerdem die Funktion
  1649. EOL benutzbar. Sie signalisiert, wenn ein Zeilentrennzeichen gelesen wurde,
  1650. das  Dateiende  erreicht  oder  ein  Fehler  aufgetreten  ist.  Ebenso  wie  das
  1651. Dateiende  kann  auch  das  Zeilenende  erst  nach  dem  Lesezugriff  erkannt
  1652. werden und, bei Read ist dann ebenfalls das erhaltene Zeichen zu verwerfen.
  1653.  
  1654. Das Zeilentrennzeichen ist ein einzelnes CR (15C) oder ein CR mit einem direkt
  1655. folgenden  LF.  Das   Anwenderprogramm   braucht   also   nicht   selbst   zu
  1656. unterscheiden, ob die Eingabe z. B. von Tastatur kommt, wo normalerweise
  1657. allein mit CR die Zeile begrenzt wird, oder von einer Datei, die meist (nicht
  1658. immer) mit CR und LF eine Zeile abschließt. Das eventuelle LF-Zeichen nach
  1659. einem CR kann beim textuellen Lesen nicht erhalten werden.
  1660.  
  1661. Es folgt ein Programmbeispiel für textuelles Lesen einer Datei mit Read:
  1662. 5.4 Bibliothek: Dateisystem                                               5 - 38
  1663. ________________________________________________________
  1664.  
  1665.  
  1666.   MODULE TestPrg;
  1667.  
  1668.   IMPORT Files, InOut;
  1669.  
  1670.   PROCEDURE LeseUndDruckeText (textname: ARRAY OF CHAR);
  1671.  
  1672.     PROCEDURE MeinFehlerTest (f: Files.File);
  1673.       VAR msg: ARRAY  0..31  OF CHAR;
  1674.       BEGIN
  1675.         IF Files.State (f) < 0 THEN            (* ernster Fehler ? *)
  1676.           Files.GetStateMsg (Files.State (f), msg);
  1677.                                                       (* Fehlertext holen *)
  1678.           Files.ResetState (f);               (* Fehler rücksetzen *)
  1679.           InOut.WriteLn;
  1680.           InOut.WriteString (msg);        (* Fehlertext anzeigen *)
  1681.         END
  1682.       END MeinFehlerTest;
  1683.  
  1684.     VAR  f: Files.File;  ch: CHAR;
  1685.  
  1686.     BEGIN
  1687.       Files.Open (f, textname, Files.readSeqTxt);
  1688.       IF Files.State (f) >= 0 THEN
  1689.         LOOP
  1690.           Text.Read (f, ch);
  1691.           IF Text.EOL (f) THEN                   (* Zeichen ungültig *)
  1692.             IF Text.EOF (f) THEN
  1693.               MeinFehlerTest (f);                          (* Fehler ? *)
  1694.               EXIT                                (* Auf jeden Fall Ende *)
  1695.             ELSE
  1696.               InOut.WriteLn                               (* Zeilenende *)
  1697.             END
  1698.           ELSE
  1699.             InOut.Write (ch);       (* gelesenes Zeichen ausgeben *)
  1700.           END
  1701.         END;
  1702.         Files.Close (f)
  1703.       END
  1704.     END LeseUndDruckeText;
  1705.  
  1706.   BEGIN (* of main *)
  1707.     LeseUndDruckeText ("KBD:");         (* Eingabe von Tastatur *)
  1708.     LeseUndDruckeText ("A:TEST.TXT")   (* Eingabe v. Diskdatei *)
  1709.   END TestPrg.
  1710. 5.4 Bibliothek: Dateisystem                                               5 - 39
  1711. ________________________________________________________
  1712.  
  1713.  
  1714. Die Leseschleife kann auch noch eleganter programmiert werden:
  1715.  
  1716.       LOOP
  1717.         Text.Read (f, ch);
  1718.         CASE State (f) OF (* siehe Kap. über Fehlerbehandlung *)
  1719.           MOSGlobals.fOK : InOut.Write (ch)| (* Zeichen ausg. *)
  1720.           MOSGlobals.fEOL: InOut.WriteLn|       (* Zeilenende *)
  1721.           MOSGlobals.fEOF: EXIT                      (* Dateiende *)
  1722.         ELSE
  1723.           MeinFehlerTest (f);EXIT
  1724.         END
  1725.       END;
  1726.  
  1727. Wie aus dem Beispiel ersichtlich ist, müssen Zeilenbegrenzer (CR und/oder LF)
  1728. über die Funktion EOL abgefragt werden. Dazu muß vorher ein  Lesezugriff
  1729. erfolgt sein. Das gleiche gilt für die Dateiende-Erkennung. Liefert die Funktion
  1730. EOF TRUE, dann kann mit Hilfe der Funktion State erkannt werden, ob das
  1731. Dateiende  (State(f)>=0)  erreicht  wurde  oder  ob  ein  Fehler  aufgetreten  ist
  1732. (State(f)<0).
  1733.  
  1734. Als letztes Beispiel die Read-Routine angepaßt für ReadString:
  1735.  
  1736.       VAR s:ARRAY  0..9  OF CHAR;
  1737.  
  1738.       ...
  1739.  
  1740.       LOOP
  1741.         Text.ReadString (f,s);
  1742.         InOut.WriteString (s);
  1743.         (* Der String ist auf jeden Fall *)
  1744.         (* brauchbar, ggf. ist er leer.  *)
  1745.         IF  Text.EOL  (f)  THEN
  1746.           IF Files.EOF (f) THEN (* Entweder Fehler o. Dateiende *)
  1747.             MeinFehlerTest (f); (* Fehler ? *)
  1748.             EXIT                     (* Auf jeden Fall Ende *)
  1749.           ELSE                       (* Zeilenende: *)
  1750.             InOut.WriteLn
  1751.           END
  1752.         END
  1753.       END;
  1754. 5.4 Bibliothek: Dateisystem                                               5 - 40
  1755. ________________________________________________________
  1756.  
  1757.  
  1758. Diverse Dateifunktionen (Modul "Files")
  1759.  
  1760. Am Ende aller Zugriffe auf eine Datei sollte sie mit Close geschlossen werden.
  1761. Vor  allem  bei  Diskdateien,  die  beschrieben  wurden,  ist  dies  unbedingt
  1762. erforderlich. Wenn Sie dies vergessen, wird bei Modulen, die von der Shell
  1763. gestartet  wurden  oder  in  die  das  Modul  GEMError  eingebunden  ist,  bei
  1764. Prozeßende eine Meldung angezeigt, die auf offen verbliebene Dateien hinweist
  1765. und sie ordnungsgemäß schließt.
  1766.  
  1767. Ist  ein  fataler  Fehler  aufgetreten  und  will  man  bereits  erzeugte  Daten
  1768. verwerfen,  kann  Remove  statt  Close  aufgerufen  werden.  Dann  werden
  1769. Diskdateien,  die  mit  Create  erzeugt  wurden,  wieder  gelöscht,  mit  Open
  1770. geöffnete Dateien werden normal, wie mit Close, geschlossen.
  1771.  
  1772. Mit SetEOFMode kann ausschließlich bei Textdateien bestimmt werden, ob und
  1773. mit  welchem  Zeichen  das  Dateiende  erkannt  werden  soll.  GetEOFMode
  1774. ermittelt die augenblickliche Einstellung für eine offene Datei. Normalerweise
  1775. wird beim Lesen des üblichen ASCII-Zeichens "ETX" (32C, $1A) das Dateiende
  1776. erkannt.
  1777.  
  1778. Flush  wird  nur  bei  Ausgabedateien  benötigt.  Es  sorgt  für  eine  unbedingte
  1779. Speicherung bzw. Übermittelung der ausgegebenen Daten. Denn es ist möglich,
  1780. daß die ausgegebenen Daten zuerst in einem rechnerinternen Speicherbereich
  1781. gesammelt werden, bevor sie auf Disk geschrieben oder z. B. über die serielle
  1782. Schnittstelle ausgegeben  werden,  damit  eine  höhere  Ausgabegeschwindigkeit
  1783. erreicht  werden  kann.  Nur  nach  dem  Aufruf  von  Flush  oder  Close  ist
  1784. sichergestellt, daß die Daten ihr Ziel erreicht haben. Normalerweise werden
  1785. also die Daten in einem normalen Ablauf immer ankommen, nur gibt es Fälle, in
  1786. denen dies zu einem bestimmten Zeitpunkt gesichert sein muß. Mit anderen
  1787. Worten: Wenn Sie nicht wissen, wofür diese Funktion gut ist, dann werden Sie
  1788. sie auch nicht brauchen. Mir fällt noch etwas ein: Beispielsweise wartet Flush
  1789. bei  einer  Datei,  die  auf  "AUX:"  geöffnet  ist,  bis  alle  Daten  des  Seriell-
  1790. Datenpuffers ausgegeben sind.
  1791.  
  1792. SetDateTimeund  GetDateTime  setzen  bzw.  erfragen  die  Zeitangabe  einer
  1793. Datei. Bei nicht-Diskdateien wird SetDateTime ignoriert und bei GetDateTime
  1794. ein Null-Datum geliefert.
  1795.  
  1796. Mit GetFileName kann man den Namen, mit dem eine Datei eröffnet wurde,
  1797. ermitteln. Ist die Datei nicht offen, wird ein Leername geliefert.
  1798. 5.4 Bibliothek: Dateisystem                                               5 - 41
  1799. ________________________________________________________
  1800.  
  1801.  
  1802. Fehlerbehandlung im Dateisystem
  1803.  
  1804. Selbstverständlich  sollte  man  nach  Aufruf  jeder  Dateibearbeitungsfunktion
  1805. eventuell aufgetretene Fehler prüfen. Dies geschieht durch Aufruf der Funktion
  1806. State,  die  einen  INTEGER-Wert  liefert.  Liefert  sie  einen  negativen  Wert,
  1807. bedeutet  dies,  daß  bei  der  letzten  Dateioperation  ein  Fehler  auftrat.  Die
  1808. Fehlernummer entspricht den TOS-Fehlernummern. Des weiteren erzeugen die
  1809. MOS-Funktionen eigene Fehlernummern, die daran erkennbar sind, daß sie alle
  1810. niedriger  als  -127  sind.  Alle  Fehlernummern  sind  im  Modul  MOSGlobals
  1811. definiert und kurz erklärt.
  1812.  
  1813. Wird  nun  aus  Nachlässigkeit  beim  Programmieren  ein  aufgetretener  Fehler
  1814. beim Dateizugriff nicht abgefragt und somit nicht erkannt, wird, sofern das
  1815. Modul GEMError vorhanden ist, beim nächsten Aufruf einer Dateibehandlungs~
  1816. funktion  das  laufende  Programm  unterbrochen  und  eine  Fehlermeldung
  1817. angezeigt, woraufhin das Programm beendet oder fortgeführt  werden  kann,
  1818. wahlweise mit Ignorieren des Fehlers, so daß er weiterhin  bestehen  bleibt,
  1819. oder  mit  Rücksetzen  des  Fehlers,  damit  weitere  Dateifunktionen  nicht
  1820. wiederholt den Fehler anzeigen.
  1821.  
  1822. Solange Sie nur kleine Programme entwickeln, reicht es auch aus, nur dort
  1823. Fehlerabfragen zu programmieren, wo ständig mit Fehlern gerechnet werden
  1824. muß:  z.  B.  nach  dem  Öffnen  einer  Datei,  um  zu  erfahren,  ob  die  Datei
  1825. vorhanden  ist,  oder  vor  allem  nach  Close,  da  hier  die  automatische
  1826. Fehlermeldung nicht mehr zuschlagen kann. Dagegen ist es ganz legitim und
  1827. auch  bequemer,  in  schnell  geschriebenen  Programmen  Fehlerabfragen  und
  1828. -meldungen nach Lese- und Schreiboperationen dem MOS zu überlassen.
  1829.  
  1830. Die automatische Fehlerprüfung wird von allen  Dateifunktionen  durchgeführt,
  1831. außer Open, Create, EOF, EOL, State, ResetState, GetStateMsg, GetFileName,
  1832. SetEOFMode und GetEOFMode.
  1833.  
  1834. Die folgenden Funktionen des Dateisystems können keine Fehler auslösen. Nach
  1835. Aufruf dieser Funktionen ist es also nicht nicht notwendig, zu prüfen, ob ein
  1836. Fehler aufgetreten ist: EOF, EOL, FileSize, FilePos, SetEOFMode, GetEOFMode,
  1837. GetFileName, State, ResetState und GetStateMsg.
  1838.  
  1839. Wird ein Fehler vom Programm erkannt, muß es zuerst den Fehler mit der
  1840. Funktion ResetState rücksetzen, damit es nicht zu einer Fehlermeldung beim
  1841. nächsten Aufruf einer Dateifunktion kommt.
  1842. 5.4 Bibliothek: Dateisystem                                               5 - 42
  1843. ________________________________________________________
  1844.  
  1845.  
  1846. Die Funktion State liefert demnach einen positiven  Wert,  wenn  bisher  kein
  1847. Fehler aufgetreten ist. In der Regel wird eine Null geliefert, jedoch kann es
  1848. auch vorkommen, daß ein Wert größer Null erhalten  wird.  Dies  signalisiert
  1849. dann besondere Zustände. Z. B. erhält man den Wert Drei, wenn Close für
  1850. eine bereits geschlossene Datei aufgerufen wurde, denn dies ist kein Fehler,
  1851. aber es kann auf der anderen Seite auch interessant sein. Außerdem kann der
  1852. Wert Eins oder Zwei geliefert werden, wenn ein Zeilenende oder das Dateiende
  1853. erreicht worden ist. Dies kann dadurch die Verwendung von EOF und  EOL
  1854. ersetzen.
  1855.  
  1856. Im allgemeinen empfiehlt sich daher, nach einer Dateioperation Fehler daran zu
  1857. erkennen, ob die Funktion State einen positiven oder negativen Wert liefert,
  1858. und nicht daran, ob State den Wert Null liefert!
  1859.  
  1860.  
  1861. Zusammenfassung der Unterschiede zwischen Binär- und Textmodus
  1862.  
  1863. Binärdateien (readOnly, writeOnly, readWrite):
  1864.     -  Es darf nur auf Disk (Floppies, Harddisks oder andere Random Access
  1865.        Devices) zugegriffen werden.
  1866.     -  Die Funktion EOF liefert schon vor einem Zugriff, ob der Dateizeiger am
  1867.        Dateiende steht.
  1868.     -  Die  Funktion  EOL  darf  nicht  verwendet  werden.
  1869.  
  1870. Textdateien  (readSeqTxt, writeSeqTxt, appendSeqTxt):
  1871.     - Es dürfen keine  Funktionen  aus  Binary  (Dateizeigeroperationen,  byte-
  1872.        weises Lesen/Schreiben, Dateilängenermittlung) verwendet werden.
  1873.     - Die Funktion EOF darf nicht auf Dateien angewandt  werden,  die  zur
  1874.        Ausgabe eröffnet wurden. Sie liefert erst nach einem Lesezugriff, ob
  1875.        noch weitere Daten folgen.
  1876. 5.4 Bibliothek: Dateisystem                                               5 - 43
  1877. ________________________________________________________
  1878.  
  1879.  
  1880. Das Modul InOut
  1881.  
  1882. Die  Funktionen  in  diesem  Modul  vereinfachen  die  Dateiein-/ausgabe.  Man
  1883. braucht sich um die Fehlerabfragen und die Besonderheiten der Dateibehand~
  1884. lung nicht zu kümmern. Normalerweise ist immer je eine Datei für Ein- und
  1885. Ausgabe über Tastatur und Bildschirm (Textwindow) geöffnet. Es stehen alle
  1886. üblichen Funktionen für textuelle Ein- und Ausgaben zur Verfügung. Da alle
  1887. Ein-/Ausgaben auf jeweils eine Standarddatei gehen, braucht bei den Funktionen
  1888. keine Dateikennung (File-Variable) übergeben zu werden.
  1889.  
  1890. Mit RedirectInput und RedirectOutputkann eine Datei bestimmt werden, auf die
  1891. die folgenden Ein- oder Ausgaben gelenkt werden. Letztere Funktion hat neben
  1892. dem Dateinamen einen weiteren Parameter, der bestimmt, ob die Datei mit
  1893. writeSeqTxt oder appendSeqTxt geöffnet werden soll.
  1894.  
  1895. OpenInput und OpenOutput geben auf dem Bildschirm einen Text aus, der dazu
  1896. auffordert, einen Dateinamen einzugeben. Tritt beim Öffnen der Datei dann ein
  1897. Fehler auf, wird eine Fehlermeldung ausgegeben und man hat die Wahl, ob die
  1898. Dateibestimmung wiederholt werden soll. Bei OpenOutput hat man weiterhin die
  1899. Möglichkeit, durch Eingabe eines ">" vor dem Dateinamen zu bestimmen, daß
  1900. die folgenden Daten an die angegebene Diskdatei angefügt werden sollen. Wird
  1901. dies nicht bestimmt, darf die Ausgabedatei nicht schon bestehen, sonst erfolgt
  1902. eine Fehlermeldung.
  1903.  
  1904. Alle vier Funktionen signalisieren über die Variable Done, ob das Öffnen der
  1905. Datei funktionierte. Wenn ein Fehler auftrat oder ein Leerstring bei OpenInput/
  1906. Output eingegeben wurde, erfolgen die weiteren Ein-/Ausgaben über Tastatur
  1907. bzw.  Bildschirm.  Done  ist  dann  FALSE.  War  vor  Aufruf  einer  der  vier
  1908. Funktionen  bereits  Ein-/Ausgabe  umgelenkt,  wird  die  alte  Datei  zuerst
  1909. geschlossen.
  1910.  
  1911. Die Ein- oder Ausgabeumleitung können Sie auch vom Anwender bestimmen
  1912. lassen, indem Sie das Modul ArgCVIO importieren und die darin enthaltene
  1913. Funktion InitArgCVaufrufen. Wenn Sie dann das Programm starten, können Sie
  1914. als Argumentzeile z. B. ">PRN:" angeben, um die Ausgaben auf den Drucker zu
  1915. leiten, oder "<IN.TXT >>OUT.TXT", damit die Eingaben aus der Datei "IN.TXT"
  1916. geholt und die Ausgaben an die Datei "OUT.TXT" angefügt werden.
  1917.  
  1918. CloseInput  und  CloseOutput  oder  ein  Fehler  während  des  Dateizugriffs
  1919.  schließen die betroffene Datei und lenken die Ein- bzw. Ausgabe wieder auf
  1920. Tastatur bzw. Bildschirm.
  1921.  
  1922. Done zeigt nach den Zahleneingabefunktionen an, ob  der  eingegebene  Wert
  1923. gültig ist. termCH enthält nach denselben Funktionen oder nach ReadString das
  1924. Zeichen, durch das die Zahlen- oder Texteingabe beendet wurde.
  1925. 5.4 Bibliothek: Dateisystem                                               5 - 44
  1926. ________________________________________________________
  1927.  
  1928.  
  1929. Konfiguration eigener Unittreiber
  1930.  
  1931. Im Modul FileBase ist ein Array namens UnitDriver deklariert. Jedes der Feld~
  1932. elemente enthält einen Namen, Prozedurvariablen und weitere Daten für ein
  1933. über das Dateisystem ansprechbares sequentielles Device (Unit).
  1934.  
  1935. Das erste Feld z. B. enthält den Unitnamen "CON:" und die Informationen, daß
  1936. diese Unit sowohl Ein- als auch Ausgaben zuläßt. Dazu sind auf die Prozedur~
  1937. variablen für zeichenweise Ein- und Ausgabe Hilfsprozeduren zugewiesen, die
  1938. die Zeichen über die BIOS-Funktionen des TOS weiterleiten. Weitere Felder
  1939. sind für "AUX:", "PRN:", "KBD:" und "MIDI:" initialisiert. Erfreulicherweise sind
  1940. auch noch sieben freie Felder vorgesehen.
  1941.  
  1942. Diese Initialisierungen werden immer vom FileBase-Modul vorgenommen. Es ist
  1943. nun aber möglich, die Ein-/Ausgabefunktionen der bestehenden Units zu ändern
  1944. oder auch weitere Units in die freien Feldern einzutragen. Sollten Sie  bei~
  1945. spielsweise verbesserte Routinen für die serielle Schnittstelle erstellt haben,
  1946. können Sie Ihre eigenen Prozeduren gegen die Standardroutinen austauschen,
  1947. ohne daß Programme, die die serielle  Schnittstelle  über  das  Modula-Datei~
  1948. system mit "AUX:" ansprechen, geändert werden müssen.
  1949.  
  1950. Wie Sie Ihre Routinen resident einbinden, erfahren Sie am Ende des Kapitels
  1951. über Prozesse.
  1952. 5.5 Bibliothek: Grafikdarstellung im Atari ST                              5- 45
  1953. ________________________________________________________
  1954.  
  1955.  
  1956. 5.5  Grafikdarstellung  im  Atari  ST
  1957.  
  1958.  
  1959. Alles, was auf dem Bildschirm zu sehen ist, wird im Speicher des Rechners
  1960. durch ein Bitraster repräsentiert. Dieses Bitraster belegt 32 kByte und ist in
  1961. planes, was soviel wie Bitebene bedeutet, unterteilt. Aus der Anzahl der Bit~
  1962. ebenen läßt sich leicht die Zahl der gleichzeitig (ohne Tricks)  darstellbaren
  1963. Farben errechnen. Es ist
  1964.  
  1965.                                                    Anzahl der Bitebenen
  1966.                             Zahl der Farben = 2
  1967.                                                                             .
  1968.  
  1969.  
  1970. Beim ST kommen normalerweise drei verschiedene Modi vor:
  1971.  
  1972. hohe Auflösung: Es ist nur eine Bitebene vorhanden, woraus sich die Anzahl
  1973.                   1
  1974. der Farben zu 2   = 2 ergibt. Dieser Modus wird auch monochrome (schwarz/
  1975. weiße) Darstellung genannt und erlaubt es, 640 x 400 einzelne Pixel (Bildpunkte)
  1976. anzusteuern;
  1977.  
  1978.                                                                        2
  1979. mittlere Auflösung: Zwei Bitebenen stehen zur Verfügung, was zu 2   = 4 ver~
  1980. schiedenen Farben führt. Bei dieser Darstellungsart können noch 640 x 200
  1981. Pixel benutzt werden. Das heißt jede Bitebene ist 640 Pixel breit und 200 Pixel
  1982. hoch;
  1983.  
  1984.                                                                             4
  1985. niedrige Auflösung: Das Raster wird in vier Bitebenen aufgeteilt, wobei 2   = 16
  1986. Farben erlaubt sind. Allerdings hat eine Bitebene dann nur noch 320 x 200
  1987. Punkte.
  1988.  
  1989. Bei den mehrfarbigen Darstellungsmodi kann jede Farbe aus einer Palette von
  1990. 512 verschiedenen Farben ausgewählt werden.
  1991.  
  1992.  
  1993. Da der Atari ST keinen speziellen Textmodus besitzt, muß auch Schrift durch
  1994. ein Bitmuster repräsentiert werden. Dafür  existieren  verschiedene  Zeichen~
  1995. sätze (fonts), die das Aussehen der einzelnen Schriftzeichen festlegen. Ist ein
  1996. Zeichensatz unproportional, so besitzen alle Zeichen die  gleiche  Breite.  Bei
  1997. einem proportionalen Font können zwei verschiedene Zeichen  hingegen  auch
  1998. unterschiedliche  Breite  haben  (Dieser  Text  wurde  zum  Beispiel  mit  einem
  1999. proportionalen Zeichensatz geschrieben). Das Betriebssystem stellt drei unpro~
  2000. portionale, sogenannte Systemfonts, zur Verfügung. Deren Ausmaße betragen
  2001. 6 x 6, 8 x 8 und 8 x 16 Pixel. Der 6 x 6 Zeichensatz wird normalerweise für
  2002. die  Beschriftung  von  Icons  (Piktogrammen)  verwendet.  Die  beiden  anderen
  2003. dienen der allgemeinen Darstellung von Schrift, wobei der 8 x 16 Font für die
  2004. 5.5 Bibliothek: Grafikdarstellung im Atari ST                              5- 46
  2005. ________________________________________________________
  2006.  
  2007.  
  2008. hohe und der 8 x 8 Font für die mittlere und niedrige Auflösung gedacht ist.
  2009. Daraus errechnet man sofort, daß bei hoher und mittlerer Auflösung 80 x 25
  2010. und bei niedriger 40 x 25 Zeichen angezeigt werden können. Bei der Darstel~
  2011. lung von Schrift muß zwischen den Ausmaßen des eigentlichen Zeichens und
  2012. denen der Zeichenzelle (auch Zeichenbox) unterschieden werden. Die  Größe
  2013. der Zeichenzelle eines Zeichens des 8 x 16 Fonts beträgt eben genau 8 x 16
  2014. Pixel, die Größe des Zeichens selber, zum Beispiel eines kleingeschriebenen i,
  2015. ist in der Regel aber geringer. Eine Zeichenzelle wird durch einige horizontale
  2016. Linien unterteilt, von denen die wichtigste die base line (Grundlinie) ist, welche
  2017. bestimmt, in welcher Höhe die Zeichen ohne Unterlängen aufliegen.
  2018. 5.6 Bibliothek: Die Line A-Routinen                                        5- 47
  2019. ________________________________________________________
  2020.  
  2021.  
  2022. 5.6  Die  Line  A-Routinen
  2023.  
  2024. Die Line A-Routinen stellen eine Sammlung von grafischen Grundfunktionen dar.
  2025. Der Name der Routinen leitet sich von der Art und Weise ihres Aufrufes ab.
  2026. Sie werden nämlich durch Opcodes der Form $Axxx aufgerufen, die im 68000
  2027. eine Ausnahmebehandlung (Exception) auslösen.
  2028.  
  2029. Dieser Aufruf auf Maschinenebene muß vom Modula-Programmierer natürlich
  2030. nicht mehr durchgeführt werden. Statt dessen importiert er die entsprechen~
  2031. den Prozeduren aus dem Modul LineA. Da ein Großteil der Parameter (zum
  2032. Beispiel Schreibmodus und Farbe) entsprechend einem $Axxx-Aufruf in einem
  2033. globalen Variablenbereich, den sogenannten Line A-Variablen, definiert werden
  2034. muß, gehört das Modul noch zu den Low-Level-Modulen. Aus diesem Grund
  2035. wird auch die Benutzung der komplexeren und komfortableren  VDI-Routinen
  2036. empfohlen. Nur in Sonderfällen sollte auf die Line A-Funktionen zurückgriffen
  2037. werden - keinesfalls  sollten  VDI-  und  Line  A-Aufrufe  in  einem  Programm
  2038. vermischt  werden,  da  dies  zu  Inkompatibilitäten  in  folgenden  Grafik~
  2039. erweiterungen (z.B. Ganzseitenbildschirm, höher auflösende Farbgrafik) führen
  2040. kann. Zur Entscheidungshilfe sei auf die Fachliteratur verwiesen (z.B. das Atari
  2041. ST Profibuch aus dem Sybex-Verlag). Die genaue Beschreibung der Routinen
  2042. steht im Anhang B. Hier sollen  nur  noch  die  verwendeten  Datenstrukturen
  2043. erklärt werden.
  2044.  
  2045.  
  2046. Der Font-Header
  2047.  
  2048. Die Muster aller Zeichen eines Zeichensatzes liegen in einem einzigen, aus ei~
  2049. ner Bitebene bestehenden Bitraster. Dort sind die Zeichen nebeneinander an~
  2050. geordnet, woraus folgt, daß die Breite des Rasters genau die Summe aller
  2051. Zeichenbreiten ist. Eine Zeile des Bitrasters wird auch als Scan-Zeile bezeich~
  2052. net. Die Anzahl der Scan-Zeilen entspricht der Höhe einer Zeichenbox, also
  2053. der maximalen Höhe eines Zeichens.
  2054.  
  2055. Um die Breite eines einzelnen Zeichens zu ermitteln, geht man folgendermaßen
  2056. vor: Man zieht vom ASCII-Wert des fraglichen Zeichens den ASCII-Wert des
  2057. ersten darstellbaren Zeichens (siehe minADE) ab. Die erhaltene Zahl stellt ei~
  2058. nen Feldindex für die Character-Offset-Tabelle dar. Aus dieser liest man den
  2059. indizierten und den darauf folgenden Wert. Subtrahiert man nun den ersten
  2060. von dem zweiten erhaltenen Wert, so ergibt sich das gewünschte Ergebnis.
  2061. Außerdem entspricht der indizierte Wert auch der x-Koordinate des Zeichens
  2062. innerhalb des Bitrasters, welches die Font-Daten enthält.
  2063.  
  2064. Die Horizontale-Offset-Tabelle wird, falls vorhanden, wie die Character-Offset-
  2065. Tabelle indiziert und enthält einen vorzeichenbehafteten Wert, um den das Zei~
  2066. chen bei der Ausgabe verschoben werden soll. Der Font-Header ist in Form
  2067. eines Verbundes (FontHeader) definiert. Die Verbund-Komponeten haben fol~
  2068. gende Bedeutung:
  2069. 5.6 Bibliothek: Die Line A-Routinen                                        5- 48
  2070. ________________________________________________________
  2071.  
  2072.  
  2073. Bezeichner           Bedeutung
  2074.  
  2075. id                     Identifikationsnummer des Zeichensatzes
  2076. size                  Größe des Fonts in Punkt (Maß aus der Satztechnik)
  2077. name                 Name des Zeichensatzes
  2078. minADE               Niedrigster im Zeichensatz enthaltener ASCII-Wert
  2079. maxADE              Höchster im Zeichensatz enthaltener ASCII-Wert
  2080. topToBase            Abstand zwischen top line und base line
  2081. ascentToBase        Abstand zwischen ascent line und base line
  2082. halfToBase           Abstand zwischen half line und base line
  2083. descentToBase       Abstand zwischen descent line und base line
  2084. bottomToBase        Abstand zwischen bottom line und base line
  2085. maxCharWidth        Maximale Zeichenbreite
  2086. maxBoxWidth         Maximale Breite einer Zeichenzelle
  2087. leftOffset             Linker Offset für Kursivschrift
  2088. rightOffset           Rechter Offset für Kursivschrift
  2089. thickening            Anzahl der Pixel, um die ein einzelnes Zeichen bei der
  2090.                       Darstellung fetter Schrift verbreitert werden soll
  2091. underLineH           Höhe des Striches für Unterstreichungen, in Pixel
  2092. lightMask             Maske zur Erzeugung aufgehellter Schrift
  2093.                       (normalerweise $5555)
  2094. skewMask            Maske zur Erzeugung schräger (kursiver) Zeichen
  2095.                       (normalerweise $5555)
  2096. flags                  Die einzelnen Bits haben folgende Bedeutung:
  2097.                       Bit 0 -- Zeigt an, daß der Header zum Systemzeichen~
  2098.                                 satz gehört
  2099.                       Bit 1  -- Zeigt an, daß die Horizontale-Offset-Tabelle
  2100.                                 benutzt wird
  2101.                       Bit 2 -- Zeigt an, daß die Font-Daten im 68000-Format
  2102.                                 (Low/High Byte) vorliegen, sonst im Intel-For~
  2103.                                 mat (High/Low Byte)
  2104.                       Bit 3 -- Zeigt an, daß alle Zeichen des Fonts gleich breit
  2105.                                 sind (also keine Proportionalschrift)
  2106.  
  2107. horOffsetTab         Zeiger  auf  die  Horizontale-Offset-Tabelle  (falls  diese
  2108.                       vorhanden ist)
  2109. charOffsetTab        Zeiger auf die Character-Offset-Tabelle
  2110. fontData              Zeiger auf das Bitraster, das die Bitmuster der Zeichen
  2111.                       enthält
  2112. formWidth            Breite einer Scan-Zeile, also die Summe aller Zeichen~
  2113.                       breiten
  2114. formHeight           Anzahl der Scan-Zeilen
  2115. next                  Zeiger auf den Font-Header des nächsten Zeichensatzes
  2116. 5.6 Bibliothek: Die Line A-Routinen                                        5- 49
  2117. ________________________________________________________
  2118.  
  2119.  
  2120. Die Line A-Variablen
  2121.  
  2122. Die Line A-Variablen dienen zur Übergabe der Parameter an die Line A-Routi~
  2123. nen. Welche Variablen von einer Routine ausgewertet werden, ist bei der Be~
  2124. schreibung der betreffenden Prozedur angegeben (Siehe Anhang B).
  2125.  
  2126. Es folgt eine Erklärung aller Line A-Variablen. Die Variablen sind in einem Ver~
  2127. bund mit dem Bezeichner LineAVars zusammengefaßt, der folgende Struktur
  2128. hat:
  2129.  
  2130. Bezeichner           Bedeutung
  2131.  
  2132. planes                Gibt die Anzahl der benutzten Bitebenen an. Wird von je~
  2133.                       der Routine, außer BitBlockTransfer, ausgewertet
  2134. bytesPerLine          Anzahl der Bytes einer Bildschirmzeile (Scan-Zeile). Wird
  2135.                       von jeder Routine, außer BitBlockTransfer,ausgewertet
  2136. contrl                 Zeiger auf das CONTRL-Array
  2137. intin                  Zeiger auf das INTIN-Array
  2138. ptsin                  Zeiger auf das PTSIN-Array
  2139. intout                 Zeiger auf das INTOUT-Array
  2140. ptsout                Zeiger auf das PTSOUT-Array
  2141. plane1                Gibt an, welchen Wert das Bit der ersten Bitebene beim
  2142.                       Setzen eines Punktes erhalten soll
  2143. plane2                Gibt an, welchen Wert das Bit der zweiten Bitebene beim
  2144.                       Setzen eines Punktes erhalten soll
  2145. plane3                Gibt an, welchen Wert das Bit der dritten Bitebene beim
  2146.                       Setzen eines Punktes erhalten soll
  2147. plane4                Gibt an, welchen Wert das Bit der vierten Bitebene beim
  2148.                       Setzen eines Punktes erhalten soll
  2149. lastLine               Wird beim Zeichnen von Linien ausgewertet und besagt,
  2150.                       ob  die  zu  zeichnende  Linie  Teil  eines  im  EXCLUSIV-
  2151.                       ODER-Schreibmodus gezeichneten Polygonzuges ist. TRUE
  2152.                       bedeutet "Linie vollständig zeichnen"
  2153. lineMask              Bitmuster für das Zeichnen von Linien
  2154. writingMode          Gibt an, in welchem Schreibmodus gezeichnet werden soll.
  2155.                       Siehe auch GrafBase.WritingMode
  2156. p                     Erster Punkt
  2157. q                     Zweiter Punkt
  2158. patternPtr            Zeigt auf das zu verwendende Füllmuster. Ein Füllmuster
  2159.                       besteht aus einer oder mehreren Bitebenen, die immer 16
  2160.                       Bit (also ein Wort) breit sind.
  2161. patternMask          Gibt an, wie viele Zeilen eine Bitebene des Füllmusters
  2162.                                                                            n
  2163.                       besitzt. Sinnvoll sind nur Zahlen, die sich durch 2   (n >
  2164.                       0) dar-stellen lassen.
  2165. multiFill               Ist diese Variable gesetzt, so besteht das Füllmuster aus
  2166.                       mehreren Bitebenen, sonst nur aus einer.
  2167. 5.6 Bibliothek: Die Line A-Routinen                                        5- 50
  2168. ________________________________________________________
  2169.  
  2170.  
  2171. clipping               Gibt an, ob der folgende Rechteckbereich als Ausgabebe~
  2172.                       grenzung benutzt werden soll. In diesem Fall werden alle
  2173.                       Punkte, die ausserhalb dieses Bereichs zu liegen kom~
  2174.                       men, unterdrückt.
  2175. minClip               Linker, oberer Punkt des Begrenzungsrechtecks
  2176. maxClip               Rechter, unterer Punkt des Begrenzungsrechtecks
  2177. scaleAcc             Dient  als  Startwert  für  den  Schriftvergrößerungs- und
  2178.                       verkleinerungsalgorithmus. Sollte bei gesetztem scale-Flag
  2179.                       (Siehe unten) mit $8000 vorbesetzt werden.
  2180. scaleFactor           Gibt den Vergrößerungs- oder Verkleinerungsfaktor  an.
  2181.                       Dabei gilt für die
  2182.                       Vergrößerung: $0000 - Normale Größe
  2183.                                          .
  2184.                                          .       Entsprechende Zwischengrößen
  2185.                                          .
  2186.                                       $FFFF  - Doppelte Größe
  2187.                       Verkleinerung: $0000 - Keine Größe (Schrumpfung auf
  2188.                                          .                      einen Punkt)
  2189.                                          .      Entsprechende Zwischengrößen
  2190.                                          .
  2191.                                       $FFFE  - Normale Größe
  2192. scaleMode
  2193.                       Gibt an ob vergrößert oder verkleinert werden soll. Ist
  2194.                        Bit 0 gesetzt, so wird vergrößert, sonst wird verkleinert
  2195. monoStatus          Zeigt an, daß die Zeichen einheitliche Breite haben. Ist
  2196.                       bei proportionalen Fonts nicht der Fall
  2197. source                Linke, obere Ecke des Zeichens im Bitraster des Fonts
  2198. dest                  Linke, obere Ecke des Zeichens auf dem Bildschirm
  2199. width                 Breite des Zeichens
  2200. height                Höhe des Zeichens
  2201. formBase             Zeiger auf den Anfang der Font-Daten (Bitraster des Fonts)
  2202. formWidth            Breite einer Scan-Zeile im Bitraster des Fonts (Angabe
  2203.                       in Bytes)
  2204. style                  Flags für spezielle Texteffekte. Es bedeutet:
  2205.                       Bit 0 -- Fette Darstellung der Schrift
  2206.                       Bit 1 -- Aufgehellte Darstellung der Schrift
  2207.                       Bit 2 -- Schrägstellen der Schrift (Kursive Darstellung)
  2208.                       Bit 3 -- Unterstreichen der Schrift
  2209.                       Bit 4 -- Umrahmte Darstellung der Schrift
  2210. lightMask             Maske zum aufgehellten Darstellen der Schrift
  2211. skewMask            Maske für kursive Schrift
  2212. weight                Anzahl der Bits, um die fette Schrift verbreitert werden
  2213.                       soll
  2214. rightOff              Rechter Offset für kursive Schrift
  2215. leftOff                Linker Offset für kursive Schrift
  2216. 5.6 Bibliothek: Die Line A-Routinen                                        5- 51
  2217. ________________________________________________________
  2218.  
  2219.  
  2220. scale                 Zeigt an, ob Schrift in ihren Ausmaßen verändert werden
  2221.                       soll
  2222. chup                  Gibt den Winkel zwischen der Zeichengrundlinie (base line)
  2223.                       und  der  horizontalen  Koordinatenachse,  entgegen  dem
  2224.                       Uhrzeigersinn  an.  Dabei  bedeutet  (Zwischenwerte  sind
  2225.                       nicht möglich):
  2226.                           0  -- Normale  Darstellung
  2227.                         900  -- Drehung um 90 Grad
  2228.                       1800  -- Drehung um 180 Grad
  2229.                       2700  -- Drehung um 270 Grad
  2230. textFg                Vordergrundfarbe für die Textdarstellung
  2231. scratchArea          Zeiger auf einen Speicherbereich, der bei der Vergrößer~
  2232.                       ung/Verkleinerung von Schrift und für Texteffekte ver~
  2233.                       wendet wird
  2234. scratchOff2          Offset für den obigen Zeiger, falls sowohl eine Größen~
  2235.                       änderung als auch Texteffekte erwünscht sind
  2236.  
  2237. Zu den beiden vorangegangenen Variablen ist folgendes zu sagen. Beim Durch~
  2238. führen einer Größenänderung von Schrift werden
  2239.  
  2240.                               Breite                       2
  2241.                             8         5
  2242.                  Höhe * (  -------   + 2)  * ( Faktor   +  1)
  2243.                             8         5
  2244.                                  8
  2245.  
  2246. Bytes von den Line A Routinen benötigt.
  2247.  
  2248. Es stehen Höhe und Breite für die Ausmaße der Zeichenzelle im Originalzu~
  2249. stand (in Pixel). Faktor gibt den Vergrößerungsfaktor an (Faktor = 1.5 bedeutet
  2250. zum Beispiel eine Vergrößerung um das Anderthalbfache). öxä steht für die
  2251. Gauß-Klammer, also den Wert von x mit abgehackten Nachkommastellen. Für
  2252. Texteffekte gilt die folgende Formel, das Resultat sind wieder die benötigten
  2253. Bytes:
  2254.  
  2255.                             Breite
  2256.                          8         5
  2257.                Höhe * (  -------   + 2)
  2258.                          8         5
  2259.                                8
  2260.  
  2261. Nur sind mit Höhe und Breite diesmal die Ausmaße des Zeichens nach der An~
  2262. wendung der Effekte gemeint.
  2263.  
  2264. Werden nur die Texteffekte oder nur die Größenänderung genutzt, so genügt
  2265. es, scratchArea auf einen genügend großen Speicherbereich weisen zu lassen.
  2266. Werden beide kombiniert angewandt, so muß der von scratchArea markierte
  2267. Bereich die Summe beider Formeln an Bytes umfassen und in scratchOff2 die
  2268. Anzahl der Bytes für die Größenänderung stehen (es dürfen nur gerade Werte
  2269. verwendet werden).
  2270. 5.6 Bibliothek: Die Line A-Routinen                                        5- 52
  2271. ________________________________________________________
  2272.  
  2273.  
  2274. textBg                Hintergrundfarbe für die Textdarstellung
  2275. copyTrans            Zeigt an, daß  die  Routine  CopyRasterForm  transparent
  2276.                       kopieren soll, sonst kopiert sie überdeckend
  2277.  
  2278.  
  2279. Der Deskriptor für BitBlockTransfer
  2280.  
  2281. Der Deskriptor enthält alle Parameter, die für die Ausführung eines BitBlock
  2282. Transfer nötig sind. Die Definition hat den Bezeichner BBTDeskriptor und ent~
  2283. hält folgende Verbund-Komponenten:
  2284.  
  2285. Bezeichner           Bedeutung
  2286.  
  2287. w                     Breite des Quellbereichs in Pixeln
  2288. h                     Höhe des Quellbereichs in Pixeln
  2289. destPlanes            Anzahl der Bitebenen (des Zielbereichs)
  2290. setBitCol             Farbe für im Quellbereich gesetzte Bits, allerdings nicht
  2291.                       als Farbindex, sondern als Bitmuster, in dem jeweils ein
  2292.                       Bit für eine Bitebene steht (Bit 0 entspricht erster Bit~
  2293.                       ebene)
  2294. unsetBitCol           Farbe für im Quellbereich ungesetzte Bits. Format  wie
  2295.                       oben.
  2296.  
  2297.                       Verknüpfungsart für Planes, bei denen das
  2298. mode00              setBitCol-Bit und das unsetBitCol-Bit gleich Null ist
  2299. mode01               setBitCol-Bit gleich Null und das unsetBitCol-Bit Eins ist
  2300. mode10               setBitCol-Bit gleich Eins und das unsetBitCol-Bit Null ist
  2301. mode11               setBitCol-Bit gleich Eins und das unsetBitCol-Bit Eins ist
  2302.  
  2303. Die sechs letzten Variablen sind nur für transparente Kopiervorgänge relevant.
  2304. Beim deckenden Kopieren wird setBitCol und unsetBitCol auf Null gesetzt und
  2305. die zu benutzende Verknüpfungsart in mode00 eingetragen.
  2306.  
  2307. Hinweis:   Zu den Verknüpfungsarten siehe GrafBase.BitOperation.
  2308.  
  2309. sourceStart          Startpunkt des Quellbereichs in Pixeln
  2310. sourceAddr           Anfangsadresse des Quellbereichs (nicht des Quellrasters)
  2311. sourceInc             Schrittweite  im  Quellbereich  in  Byte  (normalerweise:
  2312.                       Anzahl der Bitebenen des Quellbereichs * 2)
  2313. sourceWidth          Breite einer Scan-Zeile des Quellrasters in Bytes
  2314. sourceWidth2        Bei transparenter Kopie gleich Null, sonst gleich source~
  2315.                       Width
  2316. destStart             Startpunkt des Zielbereichs in Pixeln
  2317. destAddr             Anfangsadresse des Zielbereichs (nicht des Zielrasters)
  2318. destInc               Schrittweite im Zielbereich in Byte
  2319.                       (normalerweise: Anzahl der Bitebenen des Zielbereichs * 2)
  2320. 5.6 Bibliothek: Die Line A-Routinen                                        5- 53
  2321. ________________________________________________________
  2322.  
  2323.  
  2324. destWidth            Breite einer Scan-Zeile des Zielrasters in Bytes
  2325. destWidth2           Bei transparenter Kopie gleich Null,  sonst  gleich  dest~
  2326.                       Width
  2327. patternPtr            Zeiger auf ein Füllmuster, das während des Kopiervor~
  2328.                       gangs als Maske verwendt wird (Ist er NIL, so wird un~
  2329.                       maskiert kopiert.)
  2330. patternWidth         Breite einer Zeile des Füllmusters in Byte (Der aktuelle
  2331.                       Algorithmus  scheint  Probleme  mit  dieser  Variable  zu
  2332.                       haben und nimmt evtl. immer eine Breite von 2 Byte an)
  2333. patPlaneOff           Null bedeutet, daß das Füllmuster nur eine Bitebene be~
  2334.                       sitzt, sonst steht hier Zahl der Bytes für eine Bitebene.
  2335. patternEnd           Anzahl der Zeilen des Füllmusters (alle Bitebene zusam~
  2336.                       men) multipliziert mit patternWidth
  2337. scratch               Bereich, der von der Kopierroutine als Variablenspeicher
  2338.                       benutzt wird. Muß nicht initialisiert werden.
  2339. 5.7 Bibliothek: GEM                                                        5- 54
  2340. ________________________________________________________
  2341.  
  2342.  
  2343. 5.7  GEM
  2344.  
  2345. GEM steht für Graphics Environment Manager und ist schlicht und ergreifend
  2346. die  auf  dem  Atari  ST  implementierte  grafische  Benutzeroberfläche.  Dem
  2347. Programmierer stellt sie ein umfangreiches Paket an Routinen zur Verfügung,
  2348. das sowohl Dialog-, Fenster-, Menüverwaltung und ähnliches umfaßt als auch
  2349. Prozeduren   enthält,   die   eine   einheitliche   Schnittstelle   zur   Benutzung
  2350. verschiedener  Ein-  und  Ausgabegeräte  bilden.  Das  GEM  besteht  aus  zwei
  2351. großen Bibliotheken, dem VDI und dem AES.
  2352.  
  2353.  
  2354. VDI
  2355.  
  2356. Das VDI (Virtual Device Interface) umfaßt allgemeine Ein- und Ausgabeopera~
  2357. tionen, deren Benutzung von der aktuellen Implementierung der Routinen relativ
  2358. unabhängig ist.
  2359.  
  2360. Theoretisch  kann  man  zwischen  zwei  verschiedenen  Koordinatensystemen
  2361. wählen. Im
  2362.  
  2363. NDC (Normalisierte Gerätekoordinaten)-System liegt der Ursprung (0, 0) in der
  2364. linken  unteren,  Ecke  und  die  rechte  obere  Ecke  besitzt  die  Koordinaten
  2365. (32767, 32767). Dieses System hat den Vorteil einer allgemeinen Verwend~
  2366. barkeit, es ist aber im aktuellen TOS nicht implementiert;
  2367.  
  2368. RC (Raster Koordinaten)-System ist der Ursprung (0, 0) die linke, obere Ecke,
  2369. und die Koordinaten der rechten unteren Ecke hängen von der Auflösung des
  2370. Ausgabegerätes  ab;  sie  betragen  beispielsweise  auf  dem  monochromen
  2371. Bildschirm (639, 399).
  2372.  
  2373. Bei jedem Aufruf einer VDI-Prozedur muß als erster Parameter eine Geräte~
  2374. kennung (GEMEnv.DeviceHandle) übergeben werden. Diese Kennung teilt dem
  2375. VDI mit, auf welchem Gerät die Ein- oder Ausgabe stattfinden soll. Meist ist
  2376. dies  die  Kennung  für  eine  virtuelle  Bildschirmarbeitsstation  (virtual  screen
  2377. workstation). Dies bewirkt eine ganz normale Ausgabe auf den Bildschirm. Wie
  2378. erhält man nun solch eine Kennung? Dafür gibt es zwei Möglichkeiten. Erstens
  2379. kann  man  die  Routine  GEMEnv.InitGem  aufrufen  und  meldet  sich  dadurch
  2380. sowohl  beim  VDI  als  auch  beim  AES  an.  Außerdem  erhält  man,  falls  die
  2381. Anmeldung  glückt,  auch  noch  eine  Kennung  für  eine  virtuelle  Bildschirm~
  2382. arbeitsstation, mit deren Hilfe man nun auf den Bildschirm zugreifen kann. Die
  2383. zweite  Möglichkeit  besteht  in  einem  Aufruf  von  GEMEnv.OpenDevice.  Diese
  2384. Möglichkeit  sollte  aber  erst  für  das  zweite  und  folgende  Geräte  benutzt
  2385. werden.
  2386.  
  2387. Ist man mit allen Arbeiten auf dem Gerät fertig, so sollte dies mit GEMEnv.
  2388. CloseDevice geschlossen werden. Eine Beschreibung der Funktionsweise und
  2389. Parameter der einzelnen VDI-Prozeduren findet man im Anhang B.
  2390. 5.7 Bibliothek: GEM                                                        5- 55
  2391. ________________________________________________________
  2392.  
  2393.  
  2394. AES
  2395.  
  2396. Das AES (Application Environment Services) unterstützt eine Anwendung, das
  2397. heißt  ein  vom  Benutzer  gestartetes  Programm,  bei  der  Verwaltung  von
  2398. Fenstern, Dialogboxen, Menüs und ähnlichem. Außerdem ermöglicht es teilweise
  2399. eine quasiparallele Abarbeitung mehrerer Prozesse. Dies sind einerseits bis zu
  2400. sechs  Desk-Accessories  und  andererseits  die  aktuelle  Anwendung.  Da  die
  2401. Datenstrukturen und Funktionen des AES zum Teil recht komplex sind, sollen
  2402. sie im Folgenden einzeln betrachtet werden.
  2403.  
  2404.  
  2405. Das Konzept der GEM-Resourcen
  2406.  
  2407. Als Resource einer Anwendung bezeichnet man die Objekte, die zur Kommuni~
  2408. kation mit der Außenwelt dienen. Dies können zum Beispiel Dialogboxen oder
  2409. Menüzeilen  sein.  Die  GEM-Resourcen  befinden  sich  in  der  Regel  in  einem
  2410. Resource-File, das durch den Suffix .RSC  kenntlich  gemacht  wird.  Erzeugt
  2411. wird dieses File mit einem Resource Construction Set  (Siehe  auch  Anhang
  2412. C.2).  Allerdings  ist  es  auch  möglich,  die  Resourcen  zur  Laufzeit  von
  2413. Programmen selber erstellen oder ändern zu lassen (siehe Modul ObjHandler).
  2414.  
  2415.  
  2416. Verwaltung der GEM-Resourcen
  2417.  
  2418. Liegt ein Resource-File vor, so sollte dies während der Initialisierung der An~
  2419. wendung  mit  AESResources.LoadResource  geladen  werden.  Mit  Hilfe  von
  2420. AESResources.ResourceAddr und der Resource-Indizes können jetzt die Adressen
  2421. der einzelnen Objektbäume und anderer Strukturen (siehe auch Abschnitt über
  2422. Objektbäume) ermittelt werden. Die Resource-Indizes kennt eine Anwendung
  2423. durch das Importieren des Definitonsmoduls, das vom Resource Construction
  2424. Set beim Speichern der Resource erzeugt wird. Die Indizes sind in dem Modul
  2425. als Konstanten deklariert. Die Bezeichner dieser Konstanten entsprechen de~
  2426. nen, die während der Erstellung der einzelnen Objekte im Resource Construc~
  2427. tion Set eingegeben wurden. Wenn eine Resource nicht mehr gebraucht wird,
  2428. sollte ihr Speicherplatz durch AESResources.FreeResource freigegeben werden.
  2429.  
  2430.  
  2431. Die Struktur des Objektbaumes
  2432.  
  2433. Eine Resource besteht im wesentlichen aus Objektbäumen. Diese dienen sowohl
  2434. zur Beschreibung von Dialogformularen und Menüzeilen, als auch zum Erstellen
  2435. eigener Desktopoberflächen. Der Objektbaum und alle seine Elemente sind im
  2436. Modul GEMGlobals definiert.
  2437. 5.7 Bibliothek: GEM                                                        5- 56
  2438. ________________________________________________________
  2439.  
  2440.  
  2441. ACHTUNG:    Da die Typdefinitionen von Modula  und  C  (Muttersprache  des
  2442.                GEM) teilweise nicht kompatibel sind, sind die Objektdeklarationen
  2443.                oft  sehr  allgemein  gehalten.  Zum  Beispiel  ist  Object.type  als
  2444.                CARDINAL  deklariert,  obwohl  weiter  oben  ein  Typ  ObjType
  2445.                definiert  wurde,   der   ja   eigentlich   als   Wertebereich   für
  2446.                Object.type dienen soll. Der Grund dafür  ist  einfach,  daß  die
  2447.                Ordinalzahlen  für  die  Objekttypen  erst  bei  20  anfangen,  ein
  2448.                Modula-Aufzählungstyp  aber  bei  Null  beginnt.  Das  ist  alles
  2449.                ungefährlich,  solange  ausschließlich  die  Routinen  der  GEM-
  2450.                Bibliotheksmodulen  zum  Verarbeiten  der  Objekte  verwendet
  2451.                werden (Dort werden alle Typwandlungen und -transformationen
  2452.                automatisch  durchgeführt).  Sobald  man  aber  direkt  auf  die
  2453.                Objektstruktur zugreifen will, sollte man sich vorher über  die
  2454.                interne  Darstellung  von  Variablen  durch  den  Modula-Compiler
  2455.                und das GEM informieren.
  2456.  
  2457. Der Baum ist ein Feld (Array) aus Objekten (Object) und wird mit Hilfe eines
  2458. Zeigers (PtrObjTree) referenziert. Der Baumindex eines Objektes  ist  nichts
  2459. weiter als nur der Feldindex innerhalb des Baumes. Ein Objekt ist ein Verbund,
  2460. der aus einer allgemeinen Objektbeschreibung (Stellung im Baum, Größe etc.)
  2461. und  eventuell  noch  einem  Zeiger  auf  eine  typabhängige  Objektspezifikation
  2462. besteht. Dieser Verbund enthält folgende Elemente:
  2463.  
  2464. Bezeichner           Bedeutung
  2465.  
  2466. next                  Index  des  rechten  Nachbarobjektes,  entspricht  dem
  2467.                       nächsten Objekt der Nachfolgerliste (Das rechteste Ob~
  2468.                       jekt einer Nachfolgerliste enthält den Index Vorgängers)
  2469. head                  Kopf (linkestes Objekt) der Nachfolgerliste des Objekts
  2470. tail                   Ende (rechtestes Objekt) der Nachfolgerliste des Objektes
  2471.  
  2472. Ist eine der drei vorausgegangenen Variablen gleich NoObject, so existiert das
  2473. bezeichnete Objekt nicht. Das bedeutet für head und tail, daß das Objekt keine
  2474. Nachfolgerliste und somit auch keine Nachfolger besitzt. Und für next, daß
  2475. weder Nachbarn noch ein Vorgänger existieren, das heißt das Objekt ist die
  2476. Wurzel des Baumes.
  2477.  
  2478. type                  Gibt an, von welchem Typ das Objekt ist
  2479. flags                  Gibt die Flags des Objektes an
  2480. state                 Bestimmt den Objektstatus
  2481. spec                  Enthält die typabhänige Objektbeschreibung
  2482. space                 Gibt den vom Objekt belegten Rechteckbereich an. Dabei
  2483.                       ist zu beachten, daß die Position relativ zum Vorgänger~
  2484.                       objekt angegeben wird. Nur die Koordinaten des Wurzel~
  2485.                       objektes sind absolute Bildschirmkoordinaten.
  2486. 5.7 Bibliothek: GEM                                                        5- 57
  2487. ________________________________________________________
  2488.  
  2489.  
  2490. Folgende Objekttypen werden unterstützt:
  2491.  
  2492. Bezeichner           Bedeutung
  2493.  
  2494. boxObj                Stellt ein gefülltes Rechteck dar. Die Objektspezifikation
  2495.                       gibt Farbe und Randstärke an.
  2496. textObj               Steht  für  einen  Schriftzug.  Objektspezifikation  ist  ein
  2497.                       Zeiger auf eine TEdInfo-Struktur.
  2498. boxTextObj           Stellt eine Kombination der beiden vorangegangenen Ob~
  2499.                       jekttypen dar. Spezifikation wie bei textObj.
  2500. imageObj
  2501.                       Es wird ein Bitmuster dargestellt.  Spezifikation  ist  ein
  2502.                       Zeiger auf einen BitBlock-Verbund.
  2503. progDefObj           Selbstdefinierbares  Objekt.  Spezifikation  ist  ein  Zeiger
  2504.                       auf  eine  ApplBlock-Struktur.  Näheres  zu  diesem  Typ
  2505.                       kann  im  Definitionsmodul  von  ObjHandler  nachgelesen
  2506.                       werden.
  2507. iBoxObj               Dies ist ein Rechteck, von dem nur der Rahmen sichtbar
  2508.                       ist. Hat  dieser  die  Stärke  Null,  so  ist  es  unsichtbar.
  2509.                       Objektspezifikation  entspricht  boxObj.  Dieser  Objekttyp
  2510.                       wird   meist   zum   Zusammenfassen   von   mehreren
  2511.                       Unterobjekten benutzt.
  2512. buttonObj             Solche Objekte werden in der Regel als Knopf in Dialog~
  2513.                       boxen benutzt. Es wird ein Text zentriert in einem weiß
  2514.                       gefüllten Rechteck ausgegeben. Die Spezifikation ist ein
  2515.                       Zeiger auf eine Zeichenkette.
  2516. boxCharObj           Entspricht boxObj, nur wird innerhalb des Rechteckes ein
  2517.                       Zeichen zentriert dargestellt. In der Spezifikation befindet
  2518.                       sich zusätzlich noch der ASCII-Wert des Zeichens.
  2519. stringObj             Stellt  die  Zeichenkette  dar,  auf  die  die  Spezifikation
  2520.                       zeigt.  Wird  für  die  Einträge  in  den  Pull-Down-Menüs
  2521.                       verwendet.
  2522. fTextObj              Entspricht textObj, doch ist der Text hier edierbar.
  2523. fBoxTextObj          Wie fTextObj, doch wird der Text innerhalb eines gefüll~
  2524.                       ten Rechtecks dargestellt.
  2525. iconObj               Beschreibt ein Piktogramm (Icon). Dieses besteht aus ei~
  2526.                       nem maskierten Bitmuster, einer Bildunterschrift und ei~
  2527.                       nem Zeichen. Spezifikation ist ein Zeiger auf einen Icon~
  2528.                       Block-Verbund.
  2529. titleObj               Entspricht  stringObj,  wird  allerdings  für  die  Menütitel
  2530.                       verwendet.
  2531. 5.7 Bibliothek: GEM                                                        5- 58
  2532. ________________________________________________________
  2533.  
  2534.  
  2535. Es folgen die Objektflags:
  2536.  
  2537. Bezeichner           Bedeutung
  2538.  
  2539. selectFlg              Zeigt an, daß das Objekt bei einem Dialog durch einen
  2540.                       Mausklick angewählt werden kann
  2541. defaultFlg             Besitzt ein Objekt  dieses  Flag,  so  wird  es  angewählt,
  2542.                       wenn während eines Dialoges die <Return>-Taste betätigt
  2543.                       wird.  Das  Flag  sollte  pro  Dialogformular  nur  einmal
  2544.                       vorkommen.
  2545. selectExitFlg          Bestimmt, daß der Dialog abgebrochen wird, sobald das
  2546.                        so gekennzeichnete Objekt angewählt wird.
  2547. editFlg                Zeigt an, daß das Objekt einen edierbaren Text enthält.
  2548. radioButFlg           Kennzeichnet eine Gruppe von Objekten, von denen immer
  2549.                       nur  eines  gleichzeitig  angewählt  sein  kann.  Wird  ein
  2550.                       zweites angeklickt, so wird das erste wieder deselektiert.
  2551.                       Die Elemente der Gruppe müssen denselben  Vorgänger
  2552.                       besitzen.
  2553. lastObjFlg             Bestimmt das letzte Objekt eines Baumes, also das mit
  2554.                       dem größten Objektindex.
  2555. touchExitFlg          Wird auf einem solchen Objekt während des Dialoges der
  2556.                       Mausknopf gedrückt,  so  wird  der  Dialog  beendet.  Der
  2557.                       Knopf muß im Gegensatz zu selectExitObj nicht wieder
  2558.                       losgelassen werden.
  2559. hideTreeFlg
  2560.                       Das so gekennzeichnete Objekt und all seine Nachfolger
  2561.                       werden   von    einem    AESObjects.DrawObject    oder
  2562.                       AESObjects.FindObject ignoriert.
  2563. indirectFlg            Besagt,  daß  Object.spec  nicht  die  wirkliche  Objektbe~
  2564.                       schreibung, sondern nur einen Zeiger auf sie enthält.
  2565.  
  2566. Folgende Objektzustände sind möglich:
  2567.  
  2568. Bezeichner           Bedeutung
  2569. selectObj             Das Objekt wird invers dargestellt und gilt somit als an~
  2570.                       gewählt
  2571. crossObj             Es wird ein Kreuz durch das Objekt gezeichnet
  2572. checkObj             Das Objekt wird mit einem Hacken versehen
  2573. disableObj            Das Objekt wird aufgehellt. Bezeichnet nicht anwählbare
  2574.                       Objekte
  2575. outlineObj             Es wird ein Rahmen um das Objekt gezeichnet
  2576. shadowObj            Das Objekt erhält beim Zeichnen einen Schatten.
  2577.  
  2578. Die Objektspezifikation enthält grundsätzlich eine von zwei Strukturen. Entwe~
  2579. der ist sie ein Zeiger auf die eigentliche Beschreibung (zum Beispiel TEdInfo),
  2580. oder sie enthält die Objektfarbe und die Randdicke des Objektes. Letzteres ist
  2581. 5.7 Bibliothek: GEM                                                        5- 59
  2582. ________________________________________________________
  2583.  
  2584.  
  2585. bei boxObj und iBoxObj der Fall, außerdem gilt es auch für boxCharObj, nur
  2586. wird hier zusätzlich noch der ASCII-Wert des Zeichens angegeben. Die Rand~
  2587. stärke kann Werte zwischen -128 und 127 annehmen, dabei wächst der Rand
  2588. bei positiven Werten nach innen und bei negativen nach außen. Bei Objekten
  2589. vom Typ boxObj, iBoxObj, box CharObj und bei Objekten, die einen Zeiger auf
  2590. eine TEdInfo-Struktur als Spezifikation besitzen, besteht die Objektfarbe aus
  2591. folgenden Komponenten: Randfarbe, Farbe für den Text, Schreibmodus für die
  2592. Darstellung von Text (ist entweder deckend oder transparent), Füllmuster und
  2593. Füllfarbe. Es existieren 8 verschiedenen Füllmuster, dabei stehen die Werte
  2594. von 1 bis 6 für Punktmuster, die mit steigendem Wert immer dunkler werden.
  2595. 0 bedeutet keine Füllung und 7 vollständiges Füllen mit der Füllfarbe.
  2596.  
  2597. Jetzt fehlt nur noch die Beschreibung für die einzelnen Objektspezifikationen.
  2598.  
  2599.  
  2600. Die TEdInfo-Struktur
  2601.  
  2602. dient zur Beschreibung von edierbarem und nicht edierbarem Text. Ist der Text
  2603. nicht edierbar, so werden tmpltPtr und validPtr nicht ausgewertet.
  2604.  
  2605. Bezeichner           Bedeutung
  2606.  
  2607. textPtr               Zeiger auf die Zeichenkette, die den aktuellen Text ent~
  2608.                       hält
  2609. tmpltPtr              Zeiger auf die Zeichenkette, die die Textmaske enthält.
  2610.                       Der aktuelle Text wird dort in die Maske eingesetzt, wo
  2611.                       diese das '  '-Zeichen enthält. Die dadurch erzeugte Zei~
  2612.                                   _
  2613.                       chenkette wird auf dem Bildschirm dargestellt
  2614. validPtr               Zeiger  auf  die  Zeichenkette,  die  bestimmt,  welche
  2615.                       Zeichen eingegeben werden dürfen. Dabei stehen folgende
  2616.                       Character für die jeweils beschriebene Zeichenmenge:
  2617.                       9  -- Erlaubt die Ziffern von 0 bis 9
  2618.                       A -- Erlaubt alle Großbuchstaben von A bis Z und das
  2619.                              Leerzeichen
  2620.                       a  -- Erlaubt Groß- und Kleinbuchstaben und das Leer-
  2621.                              zeichen
  2622.                       F  -- Erlaubt Filenamen  mit den Sonderzeichen "?", "*"
  2623.                              und ":"
  2624.                       P  -- Erlaubt Pfadnamen mit "ü", "?", "*" und ":"
  2625.                       p  -- Erlaubt Pfadnamen mit "ü", ":"
  2626.                       X  -- Erlaubt alle Zeichen
  2627. font                  Bestimmt den zu verwendenden Zeichensatz
  2628.                       (StandardFont oder SmallFont)
  2629. res1                  Reserviert für zukünftige Anwendungen
  2630. just                   Bestimmt die Textausrichtung
  2631. color                 Bestimmt Farbe und ähnliches (siehe obige Beschreibung
  2632.                       der Objektfarbe)
  2633. 5.7 Bibliothek: GEM                                                        5- 60
  2634. ________________________________________________________
  2635.  
  2636.  
  2637. res2                  Reserviert für zukünftige Anwendungen
  2638. thickness             Randstärke
  2639. textLen               Maximallänge  des  aktuellen  Textes  (abschließende  Null
  2640.                       mitzählen)
  2641. tmpltLen              Länge der Textmaske (abschließende Null mitzählen)
  2642.  
  2643.  
  2644. Die IconBlock-Struktur
  2645.  
  2646. bestimmt das Aussehen  von  Piktogrammen.  Das  Aussehen  des  eigentlichen
  2647. Bildchens wird durch zwei Bitmuster bestimmt, die Maske und die Daten. Dies
  2648. dient dazu, daß der Hintergrund nicht durchscheinen kann und das Objekt auch
  2649. im  invertierten  Zustand  anständig  aussieht.  Die  Maske  wird  normalerweise
  2650. benutzt, um den Hintergrund dort zu löschen, wo er nicht erwünscht ist; die
  2651. Daten bestimmen dann das eigentliche Aussehen des Icons.
  2652.  
  2653. Bezeichner           Bedeutung
  2654.  
  2655. mask                 Zeiger auf das Bitmuster der Maske
  2656. data                  Zeiger auf das Bitmuster der Daten
  2657. text                  Zeiger auf die Zeichenkette der Bildunterschrift
  2658. color                 Die 4 höchstwertigen Bits enthalten den Farbindex für die
  2659.                       gesetzten Datenbits, den Schriftzug und das Zeichen. Die
  2660.                       4 niederwertigen Bits geben den Farbindex für die ge~
  2661.                       setzten Maskenbits und den Texthintergrund an
  2662. oneChar              ASCII-Wert des im Icon dargestellten Zeichens, ist er
  2663.                       gleich 0C, so wird nichts dargestellt
  2664. charPos              Position des Zeichens relativ zur Objektposition
  2665. iconFrame            Ausmaße des Bitmusters. Die Position ist relativ zu der
  2666.                       des Objektes, außerdem sollte die Breite ein Vielfaches
  2667.                       von 16 sein
  2668. textFrame            Ausmaße des Schriftzuges. Positionsangabe ist relativ
  2669.  
  2670.  
  2671. Die BitBlock-Struktur
  2672.  
  2673. beschreibt ein einfaches Bitmuster.
  2674.  
  2675. Bezeichner           Bedeutung
  2676.  
  2677. data                  Zeiger auf das Bitmuster
  2678. bytes                 Breite des Bitmusters in Byte, dieser Wert muß gerade
  2679.                       sein
  2680. h                     Höhe des Musters in Pixeln
  2681. x                     Horizontaler Offset, der es erlaubt, jedes beliebige Bit an
  2682.                       den linken Rand zu setzen
  2683. y                     Vertikaler Offset
  2684. 5.7 Bibliothek: GEM                                                        5- 61
  2685. ________________________________________________________
  2686.  
  2687.  
  2688. color                 Farbindex für das Bitmuster
  2689.  
  2690.  
  2691. Die ApplBlock-Struktur
  2692.  
  2693. beschreibt ein selbstdefinierbares Objekt. Dies geschieht, indem eine Prozedur
  2694. angegeben wird, die das Objekt wahlweise zeichnet oder seinen Status ändert.
  2695. Der Prozedur kann ein 32 bit breiter Parameter übergeben werden, der das
  2696. Aussehen des Objektes näher beschreibt. Will man solch ein Objekt ohne die
  2697. Routinen des Moduls ObjHandler benutzen, so hat man darauf zu achten, daß
  2698. zum Zeitpunkt des Aufrufs  der  Zeichenprozedur  die  Registerbelegung  nicht
  2699. mehr den Modulakonventionen entspricht.
  2700.  
  2701. Bezeichner           Bedeutung
  2702.  
  2703. code                  Startadresse  der  Zeichenprozedur.  Die  Prozedur  be~
  2704.                       kommt beim Aufruf einen Zeiger auf einen ParmBlock-
  2705.                       Verbund übergeben.
  2706. parm                 Parameter für die Prozedur
  2707.  
  2708.  
  2709. Das Konzept der AES-Menuleisten
  2710.  
  2711. Die Menuleisten werden mit Hilfe eines Objektbaumes dargestellt und sollten
  2712. mit dem Resource Construction Set erstellt werden. Die Routinen zum Benut~
  2713. zen der Pull-Down-Menus finden sich in dem Modul AESMenus. Die wichtigste
  2714. von ihnen ist MenuBar, mit ihr werden die Menus aktiviert und auch wieder
  2715. ausgeschaltet. Ein aktives Menu kann vom Anwender mit der Maus bedient
  2716. werden. Wird ein Menupunkt angewählt, so erhält man ein Nachrichtenereignis
  2717. mit der Kennung AESEvents.menuSelected.
  2718.  
  2719.  
  2720. Accessories
  2721.  
  2722. Accessories werden mit Hilfe der Prozedur AESMenus.RegisterAcc beim AES
  2723. angemeldet. Nach der Anmeldung erscheint der Titel des Accessory's in jedem
  2724. Menu und kann damit vom Benutzer angewählt werden. Wird es selektiert, so
  2725. wird ihm eine Nachricht mit der Kennung AESEvents.accOpen gesendet, dabei
  2726. übergibt das AES zur Kontrolle die bei der Anmeldung erhaltene Accessory-
  2727. Kennung.
  2728. 5.7 Bibliothek: GEM                                                        5- 62
  2729. ________________________________________________________
  2730.  
  2731.  
  2732. Das Konzept der AES-Fenster
  2733.  
  2734. Fenster dienen zum Darstellen von Informationen, sie sind in ihrer Größe und
  2735. Position frei veränderbar und dürfen sich auch überlappen (Alle Prozeduren zur
  2736. Fensterbehandlung  findet  man  in  AESWindows).  Welche  Bedienungselemente
  2737. (Schieber,  Titelzeile  etc.)  ein  Fenster  besitzt,  wird  von  dem  Anwendungs~
  2738. programm während der Anforderung einer Fensterkennung mit CreateWindow
  2739. festgelegt. Erhält die Anwendung eine Kennung ungleich NoWindow, so war die
  2740. Anforderung  erfolgreich,  und  diese  Kennung  muß  dann  immer  als  erster
  2741. Parameter bei allen  Funktionen  angegeben  werden,  die  auf  diesem  Fenster
  2742. arbeiten  sollen.  Wird  ein  Fenster  nicht  mehr  benötigt,  so  sollte  die
  2743. Fensterkennung mit DeleteWindow freigegeben werden.
  2744.  
  2745. Soll  das  Fenster  nun  auf  dem  Bildschirm  dargestellt  werden,  so  muß
  2746. OpenWindow aufgerufen werden. Es ist nun sichtbar, und die Anwendung muß
  2747. dafür sorgen, daß, sobald das AES eine entsprechende Nachricht schickt, der
  2748. Fensterinhalt erneuert wird. Soll das Fenster wieder verschwinden, so wird
  2749. dies  dem  AES  mittels  Close  Window  mitgeteilt.  Mit  OpenWindow  kann  es
  2750. daraufhin jederzeit wieder sichtbar gemacht werden, und der Ablauf beginnt
  2751. von Neuem. Wird ein Fenster geöffnet, in seiner Größe verändert oder ein
  2752. darüberliegendes  Fenster  verschoben,  so  kann  es  passieren,  daß  plötzlich
  2753. sichtbar werdende Fensterinhalte der Neuzeichnung  (redraw)  bedürfen.  Eine
  2754. solches  Ereignis  veranlaßt  das  AES,  eine  Nachricht  zur  Neuzeichnung
  2755. AESEvents.windRedraw   zu   schicken.   Wird   diese   von   der   Anwendung
  2756. empfangen, so wird im Regelfall ein Aktualisieren des Fensters angekündigt und
  2757. der Mauszeiger versteckt. Jetzt wird die Rechteckliste vom AES geholt und
  2758. der angegebene Bereich neu gezeichnet. Schlußendlich  wird  der  Mauszeiger
  2759. wieder sichtbar gemacht und das Ende der Neuzeichnung gemeldet.
  2760.  
  2761. Die folgende Prozedur soll dies verdeutlichen; sie geht davon aus, daß dev eine
  2762. virtuelle Bildschirmarbeitsstation (siehe VDI) ist. Ihr wird die Fensterkennung
  2763. (handle) und der neuzuzeichende Bereich (frame) übergeben.
  2764. 5.7 Bibliothek: GEM                                                        5- 63
  2765. ________________________________________________________
  2766.  
  2767.  
  2768. PROCEDURE RedrawFrame (handle:CARDINAL;
  2769.                               frame:GrafBase.Rectangle);
  2770.  
  2771. VAR     clip : GrafBase.Rectangle;
  2772.  
  2773. BEGIN
  2774.                (* Füllattribute für 'Bar' bestimmen *)
  2775.  
  2776.   VDIAttributes.SetFillType (dev, VDIAttributes.solidFill);
  2777.   VDIAttributes.SetFillColor (dev, GrafBase.white);
  2778.  
  2779.                (* Aktualisierung ankündigen und Mauszeiger aus *)
  2780.  
  2781.   UpdateWindow  (TRUE);
  2782.   AESGraphics.GrafMouse (AESGraphics.mouseOff, NIL);
  2783.  
  2784.                (* 1. Element der Reckteckliste holen *)
  2785.  
  2786.   clip:=WindowRectList (handle, firstElem);
  2787.  
  2788.   WHILE clip.w # 0 DO      (* 'w = 0' kennzeichnet Listenende *)
  2789.  
  2790.                (*  Schnittbereich ermitteln und
  2791.                 *  Ausgabebereich beschränken
  2792.                 *)
  2793.      clip:=GrafBase.ClipRect (frame, clip);
  2794.      VDIControls.SetClipping (dev, clip);
  2795.  
  2796.      VDIOutputs.Bar (dev, clip);  (* Bereich mit Weiß füllen *)
  2797.  
  2798.          (*  Hier können noch andere Sachen gezeichnet werden *)
  2799.  
  2800.                 (* Nächstes Element der Rechteckliste holen *)
  2801.  
  2802.      clip:=WindowRectList (handle, nextElem);
  2803.  
  2804.   END;
  2805.  
  2806.   VDIControls.DisableClipping (dev);        (* Clipping aus *)
  2807.  
  2808.                (* Mauszeiger ein und Aktualisierungsende melden *)
  2809.   AESGraphics.GrafMouse (AESGraphics.mouseOn, NIL);
  2810.   UpdateWindow (FALSE);
  2811. END RedrawFrame;
  2812. 5.7 Bibliothek: GEM                                                        5- 64
  2813. ________________________________________________________
  2814.  
  2815.  
  2816. Die Funktion der anderen (Fenster betreffenden) Nachrichten kann im Definitions~
  2817. modul AESEvents und im Abschnitt über Ereignisse nachgelesen werden.
  2818.  
  2819. Neben den oben beschriebenen Fenstern existiert noch ein weiteres. Es ist das
  2820. Desktop-Fenster, welches die Kennung DeskHandle besitzt. Neuzeichnungen des
  2821. Desktops müssen nicht von der Anwendung durchgeführt werden, sie sind Auf~
  2822. gabe des AES. Dies hat natürlich den Nachteil, daß das Aussehen des Desk~
  2823. tops im wesentlichen immer gleich ist. Dieser Nachteil wurde dadurch ausge~
  2824. schaltet, daß es möglich ist, einen beliebigen Objektbaum mit SetNewDesk als
  2825. Desktopoberfläche zu benutzen.
  2826.  
  2827. Bei allen Aufgaben, die von der Größe des Desktops abhängen, sollten eben
  2828. diese Ausmaße durch einen Aufruf von WindowSize (DeskHandle, workSize)
  2829. ermittelt werden.  Es  wird  die  Bildschirmgröße,  abzüglich  der  Menuzeile,  in
  2830. Pixeln geliefert.
  2831.  
  2832.  
  2833. Das Konzept der AES-Ereignisse
  2834.  
  2835. Die Ereignisse stellen meist Aktionen des Anwenders dar und werden mit den
  2836. Routinen des Moduls AESEvents überwacht. Es existiert die Möglichkeit, die
  2837. Ereignisse entweder einzeln oder zusammen  zu  überwachen.  Letzteres  ge~
  2838. schieht durch MultiEvent und wird meist benutzt. Dabei stehen die folgenden
  2839. Ereignisse zur Auswahl:
  2840.  
  2841. keyboard -- Das Tastatur-Ereignis tritt ein, sobald eine Taste gedrückt wird.
  2842. Als  Ergebnis  wird  sowohl  der  IBM-Scan-Code  der  Taste  als  auch  deren
  2843. ASCII-Äquivalent, falls vorhanden, geliefert (siehe GEMGlobals.GemChar).
  2844.  
  2845. mouseButton -- Ein Mausknopf-Ereignis tritt auf, sobald eine vorher bestimmte
  2846. Kombination  der  Maustasten  gedrückt  ist.  Die  Maske  bestimmt,  welche
  2847. Mausköpfe berücksichtigt werden sollen (Ist sie die leere Menge, so tritt das
  2848. Ereignis  auf  alle  Fälle  ein).  Der  Status  bestimmt  nun,  welche  Knöpfe  der
  2849. Maske  gedrückt  sein  müssen,  damit  das  Ereignis  auftritt.  Außerdem  kann
  2850. angegeben  werden,  auf  bis  zu  wie  viele  solche  sich  schnell  wiederholende
  2851. Zustände  gewartet  werden  soll  (Anzahl  der  Mausklicks).  Die  minimale
  2852. Wiederholgeschwindigkeit  kann  mit  SetDClickSpeed  eingestellt  werden.  Als
  2853. Ergebnis liefert dieses Ereignis die Position der Maus, die zur Zeit gedrückten
  2854. Maustasten und Sondertasten der Tastatur und außerdem, wie oft der Zustand
  2855. der Maustasten eingetreten ist (Mausklicks).
  2856.  
  2857. firstRect, secondRect -- Ein Maus-Ereignis tritt auf, sobald sich der Mauszei~
  2858. ger innerhalb oder außerhalb eines bestimmten Rechteckbereichs befindet. Als
  2859. Ergebnis erhält man die Position des Zeigers, die gedrückten Mausknöpfe und
  2860. Sondertasten der Tastatur (Dies sind <Alternate>, <Control> und  die  beiden
  2861. <Shift>-Tasten).
  2862. 5.7 Bibliothek: GEM                                                        5- 65
  2863. ________________________________________________________
  2864.  
  2865.  
  2866. timer -- Das Zeitgeber-Ereignis erfüllt zwei verschiedene Funktionen. Erstens
  2867. kann die Anwendung es dazu nutzen, nach einer  gewissen  Zeitspanne  eine
  2868. Meldung zu erhalten, und zweitens können damit andere Prozesse Rechenzeit
  2869. zugeteilt  bekommen.  Letzteres  nutzt  im  aktuellen  Betriebssystem  aber  nur
  2870. Accessories etwas.
  2871.  
  2872. message  --  Nachrichten-Ereignisse  dienen  zur  Kommunikation  mit  anderen
  2873. Prozessen, in der Regel dem AES oder einem Accessory. Ein solches Ereignis
  2874. füllt ein varianten Verbund vom Typ MessageBuffer, der im ersten Wort immer
  2875. die Art der Nachricht, im zweiten die Applikationsnummer des Senders und im
  2876. dritten die Anzahl der Bytes, die über die 16 Standardbytes hinausgehen, ent~
  2877. hält.
  2878.  
  2879. Der Bezeichner für die Applikations-Identifikationsnummer endet immer auf Id
  2880. und der für die über 16 hinausgehenden Bytes auf Rmd (siehe MessageBuffer).
  2881.  
  2882. Es existieren folgende Nachrichtentypen:
  2883.  
  2884. unspecMessage  --  Bezeichnet  eine  nicht  vom  AES,  sondern  von  einer
  2885. beliebigen anderen Anwendung kommende Nachricht. In uMsgData steht  der
  2886. Anfang  der  Nachricht,  deren  Format  vom  Sender  abhängt.  Möglicherweise
  2887. folgen noch mehr als die 16 normalen Bytes, die dann mit AESMisc.ApplRead
  2888. gelesen werden müssen.
  2889.  
  2890. menuSelected -- Diese Nachricht wird gesendet, nachdem der Anwender einen
  2891. Eintrag in einem Menu angewählt hat. In selTitle steht der Index des Titels, in
  2892. dem sich der Menupunkt befindet, und in selItem steht der Index des Eintrags.
  2893. Der Menutitel muß vom Programm mit AESMenus.NormalTitle wieder normal
  2894. dargestellt werden.
  2895.  
  2896. windRedraw  --  Diese  Nachricht  besagt,  daß  ein  Fensterausschnitt  neu
  2897. gezeichnet werden muß (siehe auch Abschnitt über Fenster). Dabei steht in
  2898. rdrwHdl die Kennung des Fensters, welches aktualisiert werden soll, und in
  2899. rdrwFrame der neu zu zeichnende Rechteckbereich.
  2900.  
  2901. windTopped  --  Eine  Nachricht  dieser  Art  zeigt  an,  daß  ein  Fenster  vom
  2902. Anwender angeklickt wurde und es deshalb noch oben gebracht werden soll.
  2903. Dadurch  wird  es  aktiv,  das  heißt,  seine  Randelemente  werden  dargestellt.
  2904. topHdl enthält die Kennung des angewählten Fensters.
  2905.  
  2906. windClosed -- Solch eine Nachricht wird gesendet, nachdem der Anwender auf
  2907. die Schließbox (links oben) eines Fensters geklickt hat. Daraufhin sollte das
  2908. Fenster mit der Kennung clsHdl geschlossen werden.
  2909.  
  2910. windFulled -- Diese Nachricht besagt, daß die Vergrößerungsbox (rechts oben)
  2911. des Fensters, mit der Kennung fullHdl, angeklickt wurde. Das Fenster sollte
  2912. nun in seiner Maximalgröße dargestellt werden.
  2913. 5.7 Bibliothek: GEM                                                        5- 66
  2914. ________________________________________________________
  2915.  
  2916.  
  2917. windArrowed -- Es wird mitgeteilt, daß der Benutzer auf einen Scroll-Pfeil
  2918. oder  einen  Schieber  geklickt  hat,  und  daß  der  Inhalt  des  entsprechende
  2919. Fensters (arrwHdl) jetzt verschoben werden sollte, wie es arrwMode angibt.
  2920.  
  2921. windHSlid -- Besagt, daß der Schieber des Fensters mit der Kennung hSldHdl
  2922. in  die  von  horPos  spezifizierte  Position  gebracht  wurde.  Der  Inhalt  des
  2923. Fensters sollte daraufhin entsprechend verändert werden. Die Positionsangabe
  2924. erfolgt in Promille (siehe auch  WSliderValue)  und  gilt  für  den  horizontalen
  2925. Schieber.
  2926.  
  2927. windVSlid  --  Entspricht  windHSlid,  allerdings  ist  die  Angabe  nun  für  den
  2928. vertikalen  Schieber  gedacht.  Die  Kennung  ist  vSldHdl  und  vertPos  ist  die
  2929. Position.
  2930.  
  2931. windSized -- Diese Nachricht wird gesendet, nachdem der Benutzer die Größe
  2932. eines  Fensters  verändert  hat.  In  sizeHdl  steht  die  Fensterkennung  und  in
  2933. sizeFrame  befinden  sich  die  neuen  Fensterausmaße.  Zum  Zeitpunkt  dieser
  2934. Nachricht  hat  das  Fenster  noch  die  alte  Größe,  die  neue  muß  erst  noch
  2935. gesetzt werden.
  2936.  
  2937. windMoved  --  Zeigt  an,  daß  das  Fenster,  welches  die  Kennung  moveHdl
  2938. besitzt, verschoben wurde. Die neue Position, die erst noch gesetzt werden
  2939. muß, steht in moveFrame.
  2940.  
  2941. windNewTop -- Solch eine Nachricht wird gesendet, nachdem das Fenster mit
  2942. der Kennung nwTpHdl nach oben gebracht wurde.
  2943.  
  2944. accOpen  --  Diese  Nachricht  erhält  ein  Accessory,  nachdem  der  ihm
  2945. zugeordnete  Menutitel  angewählt  wurde.  Die   Identifikationsnummer   des
  2946. Accessories wird in aOpnMId geliefert. aOpnVoid dient nur als Platzhalter.
  2947.  
  2948. accClose -- Hiermit wird einem Accessory mitgeteilt, daß es vom Bildschirm
  2949. verschwinden muß. Dieser Fall kann eintreten, falls die laufende Anwendung
  2950. terminiert, der Bildschirm gelöscht wird oder die AES-Fensterbibliothek  neu
  2951. initialisiert wird.
  2952.  
  2953.  
  2954. Mit Hilfe der AESMisc.ApplWrite-Routine kann einer Anwendung eine Nachricht
  2955. übermittelt werden. Damit diese korrekt ankommt, muß die Applikationsnummer
  2956. des Empfängers angegeben werden und dieser muß auf ein Nachrichtenereignis
  2957. warten. Die Applikationsnummer einer Anwendung kann mit Hilfe von AESMisc.
  2958. ApplFind ermittelt werden. Das  erste  Wort  der  Nachricht  sollte  den  Wert
  2959. unspecMessage besitzen, das zweite die Identifikationsnummer  des  Senders
  2960. und das dritte die  Länge  der  Nachricht  minus  16  Byte,  falls  die  Gesamt~
  2961. nachricht länger als 16 Byte ist.
  2962. 5.7 Bibliothek: GEM                                                        5- 67
  2963. ________________________________________________________
  2964.  
  2965.  
  2966. MEGA-GEM oder 'Eine Modula-Anpassung des GEM'
  2967.  
  2968. Die  vorliegende  GEM-Bibliothek  ist  nicht  einfach  eine  Konvertierung  der
  2969. bekannten  C-Vorlagen,  sondern  sie  paßt  GEM  an  Modula  an  und  nicht
  2970. umgekehrt. Dies hat den Nachteil, daß alte Programme nicht ganz so einfach
  2971. zu übernehmen sind, bietet dafür aber die Vorteile,
  2972.  
  2973. -- daß  die  Programme  sehr  viel  übersichtlicher  werden,  da  erstens  die
  2974.     Namensgebung  aussagekräftiger  ist  und  zweitens  sinnvolle  Verbunde
  2975.     geschaffen wurden, so daß die Prozeduren weniger Parameter besitzen und
  2976.     zum Beispiel bei der Beschreibung eines Punktes nicht mehr die x- und die
  2977.     y-Komponente  getrennt  deklariert  werden  müssen,  sondern  eine  einzige
  2978.     Variable vom Typ Point ausreicht;
  2979.  
  2980. -- daß ein Programm, das während der Testphase abstürzt, ohne sich vorher
  2981.     beim GEM abzumelden, nicht gleich das gesamte System mit sich reißt,
  2982.     sondern  die  erforderlichen  Abmeldungen  automatisch  von  der  Bibliothek
  2983.     ausgeführt werden;
  2984.  
  2985. -- daß der Benutzer sich  an  die  Programmierung  selbstdefinierter  Objekte
  2986.     oder Interruptvektoren wagen kann, ohne  erst  einmal  die  Innereien  des
  2987.     Rechners und die Funktionsweise des Mikroprozessors zu studieren;
  2988.  
  2989. -- daß Fehler im Programm frühzeitig vom Laufzeitsystem erkannt werden,
  2990.     weil eine Variable den Bereich eines Aufzählungstypen verlassen hat (was
  2991.     oft das Neubooten des Rechners erspart);
  2992.  
  2993. -- daß die Programmierung einfach komfortabler geworden ist.
  2994.  
  2995. Wie oben erwähnt, wird bei der Terminierung eines Programmes, egal ob diese
  2996. gewollt  oder  ungewollt  ist,  dafür  gesorgt,  daß  eventuell  noch  ausstehende
  2997. Abmeldungen  beim  GEM  durchgeführt  werden.  Dies  beinhaltet  zum  Beispiel
  2998. auch, noch aktive Fenster zu schließen und abzumelden oder den Mauszeiger
  2999. wieder sichtbar zu machen. Dabei werden nur solche Aktionen aufgehoben, die
  3000. unter der Modulkennung des terminierenden Moduls vorgenommen wurden. Da
  3001. es  aber  Modulen  gibt,  bei  denen  diese  automatische  Abmeldung  nicht
  3002. gewünscht  ist,  zum  Beispiel  residente  oder  Systemmodulen,  gibt  es  die
  3003. Möglichkeit, sich mit GEMEnv.SysInitGem anzumelden und damit eine Kennung
  3004. zu erhalten, die vor der Abmeldung geschützt ist. Die An-  und  Abmeldung
  3005. geschieht in der Regel folgendermaßen:
  3006. 5.7 Bibliothek: GEM                                                        5- 68
  3007. ________________________________________________________
  3008.  
  3009.  
  3010. IMPORT GEMEnv;
  3011. FROM GEMGlobals IMPORT RC;
  3012.  
  3013. VAR      dev      : GEMEnv.DeviceHandle;
  3014.          gemHdl  : GEMEnv.GemHandle;
  3015.          success : BOOLEAN;
  3016.  
  3017. BEGIN
  3018.      (*  Anmelden.  Gleichzeitig erhält man in 'dev' die Geräte-
  3019.       *                 kennung für eine virtuelle Arbeitsstation.
  3020.       *)
  3021.  
  3022.   GEMEnv.InitGem (RC, dev, success);
  3023.   IF success THEN (* Falls Anmeldung erfolgreich war, dann ...*)
  3024.  
  3025.                                      (* Eigene GEM-Kennung ermitteln *)
  3026.  
  3027.      gemHdl:=GEMEnv.CurrGemHandle ();
  3028.           .
  3029.           .                         (* Hauptprogramm ausführen *)
  3030.           .
  3031.      GEMEnv.ExitGem (gemHdl); (* Abmelden *)
  3032.  
  3033.   ELSE
  3034.  
  3035.      (*  User mitteilen,
  3036.       *  daß Anmeldung beim GEM
  3037.       *  nicht erfolgreich war.
  3038.       *)
  3039.  
  3040.   END;
  3041. END ... .
  3042.  
  3043.  
  3044. Der Aufruf von InitGem ersetzt die Einzelaufrufe zur Anmeldung beim AES
  3045. (appl init) und das  Öffnen  einer  "virtual  workstion"  (v opnvwk)  beim  VDI.
  3046.      _                                                      _
  3047. Wenn  Sie  aber  keine  VDI-Funktionen  aufzurufen  haben  -  das  kommt
  3048. beispielsweise oft bei Accessories vor - können Sie mit GemEnv.InitApplication
  3049. nur die AES-Anmeldung durchführen. Mit GemEnv.OpenDevice können Sie dann
  3050. immer noch nachträglich das Öffnen der des Bildschirms beim VDI nachholen.
  3051. Mehr dazu im Definitionstext von GemEnv.
  3052. 5.7 Bibliothek: GEM                                                        5- 69
  3053. ________________________________________________________
  3054.  
  3055.  
  3056. Zur Fehlerbehandlung ist folgendes zu sagen. Tritt zum Beispiel ein Fehler auf,
  3057. weil ein ARRAY OF CHAR übergeben wurde, das zu wenig Elemente enthält, so
  3058. wird ein ganz normaler Laufzeitfehler  ausgelöst,  in  diesem  Fall  ein  'String
  3059. Overflow'. Tritt der Fehler aber innerhalb einer ROM-Routine des GEM auf, so
  3060. meldet diese den Fehler in der Regel mit Hilfe eines INTEGER-Wertes. Dieser
  3061. Wert wird nicht direkt an das aufrufende Modul weitergeleitet, sondern der
  3062. Fehler  muß  von  diesem  durch  den  Aufruf  von  GEMEnv.GemError  erkannt
  3063. werden.  Ist  dies  geschehen,  so  kann  der  eigentliche  INTEGER-Wert  mit
  3064. GEMEnv.ErrorNumber  ermittelt  werden.  Tritt  ein  Fehler  auf,  der  nicht  mit
  3065. GemError abgefragt wird, so wird eine Fehlerroutine ausgeführt. Näheres dazu
  3066. im Defintionsmodul GEMEnv (Anhang B).
  3067.  
  3068. Die Aufteilung der einzelnen Routinen auf die Module entspricht der logischen
  3069. Anordnung  innerhalb  des  GEM.  Lediglich  die  Routinen  des  "Application
  3070. Manager", des "File Selector Manager", des "Scrap Manager" und des "Shell
  3071. Manager" sind in AESMisc zusammengefaßt, da diese "Manager" sehr wenig
  3072. Routinen  enthalten.  Außerdem  befinden  sich  alle  Initialisierungsroutinen  in
  3073. GEMEnv. Die Namen sind normalerweise an die orginal C-Namen angelehnt, so
  3074. daß sich ein GEM-gewohnter Programmierer innerhalb kurzer Zeit zurecht~
  3075. finden sollte.
  3076.  
  3077.  
  3078. Eine Stufe über GEM
  3079.  
  3080. Ein Grund für eine Benutzeroberfläche nach Art des GEM ist wohl, daß sich
  3081. der Programmierer einer Anwendung nicht mehr mit den Details der Ein- und
  3082. Ausgabe befassen muß. In diesem Bereich ist der Schuß beim GEM ein wenig
  3083. nach hinten losgegangen. Der Programmautor muß zwar nicht unbedingt wissen
  3084. wieviele Pixel zur Laufzeit auf dem Bildschirm vorhanden sind, doch ist er oft
  3085. mit  der  Bedienung  des  GEM  so  beschäftigt,  daß  er  für  sein  eigentliches
  3086. Problem kaum noch Zeit hat.
  3087.  
  3088. Um  diesen  Makel  ein  wenig  zu  beheben,  gibt  es  sieben  Module,  die  den
  3089. Umgang mit GEM ein wenig erleichtern sollen. Als erstes soll der ObjHandler
  3090. erwähnt werden. Dieses Modul ermöglicht es, die Objektbäume auf einer Ebene
  3091. zu  bearbeiten,  auf  der  es  nicht  nötig  ist,  genau  über  die  Abbildung  der
  3092. Struktur im Speicher informiert zu sein. Es genügt, die einzelnen Objektbaum~
  3093. elemente  und  ihre  Funktion  zu  kennen.  Auch  die  Typwandlungen  und
  3094. -transformationen werden für die einzelnen Variablen selbständig durchgeführt
  3095. (siehe auch Abschnitt über Objektbäume). Sozusagen als kleines Bonbon ist es
  3096. mit dem ObjHandler auch sehr einfach, die Möglichkeit der selbstdefinierbaren
  3097. GEM-Objekte zu nutzen.
  3098.  
  3099. Das zweite Modul heißt EventHandler und nimmt dem Programmierer einen Teil
  3100. der  immer  wiederkehrenden  Tipparbeit  bei  der  Ereignisverwaltung  ab.  Es
  3101. werden für jedes Ereignis einfach Prozeduren angemeldet, deren Verwaltung
  3102. vom EventHandler übernommen wird. Tritt nun ein Ereignis auf, so werden die
  3103. 5.7 Bibliothek: GEM                                                        5- 70
  3104. ________________________________________________________
  3105.  
  3106.  
  3107. zugehörigen Prozeduren mit den entsprechenden Parametern aufgerufen. Dabei
  3108. gibt es auch die Möglichkeit, Prozeduren anzumelden, die den Ereignisstrom
  3109. aller Module, die diese GEM-Bibliothek benutzen, überwachen und filtern können.
  3110.  
  3111. Des weiteren gibt es das Modul TextWindows, das, wie der Name schon sagt,
  3112. die Verwaltung von Textfenstern übernimmt. Ein solches Textfenster wird von
  3113. dem   Anwendungsprogramm   wie   ein   ganz   gewöhnlicher   Textbildschirm
  3114. behandelt,  das  heißt  die  Prozeduren  entsprechen  denen  von  Terminal.  Alle
  3115. Operationen, wie das Reagieren auf Mausoperationen des Anwenders und das
  3116. Neuzeichnen  des  Fensterinhaltes  werden  von  TextWindows  automatisch
  3117. durchgeführt. Als kleines Extra ist es damit möglich, einzelne Zeichen vom
  3118. Benutzer mit Hilfe des Mauszeigers anwählen zu lassen. So kann man z.B.
  3119. Textbereiche aus einem Fenster herausziehen lassen oder sie markieren.
  3120.  
  3121. Ein weiteres Modul trägt den Namen EasyGEM0 und enthält eine Reihe von
  3122. Routinen, die bei der GEM-Programmierung des öfteren gebraucht werden. Die
  3123. Programmierung von Dialogboxen wird durch Routinen unterstützt, die eine Box
  3124. darstellen,  einzelne  Objekte  animieren  und  die  Box  zum  Schluß  wieder
  3125. entfernen. Einfache Dialoge können sogar mit einem einzigen Prozeduraufruf
  3126. abgehandelt  werden.  Außerdem  gibt  es  Prozeduren,  die  die  Objekte  von
  3127. Dialogboxen mit Startwerten vorbelegen und die Ergebnisse auslesen.
  3128.  
  3129. EasyGEM1  stellt  Funktionen  zum  Verwalten  eines  Clipboards  und  einen
  3130. komfortablen Aufruf der Dateiauswahlbox (FileSelector) zur Verfügung.
  3131.  
  3132. Das Modul WindowBase dient zum Verwalten von Fenstern beliebigen Inhalts.
  3133. Das Verhalten und der  Inhalt  der  Fenster  wird  durch  eine  Reihe  von  frei
  3134. wählbaren  Prozedurvariablen  bestimmt.  Die  gesamte  Fensterverwaltung  ist
  3135. dabei  weitgehend  automatisiert  worden,  so  daß  das  Programmieren  von
  3136. Fenstern möglichst einfach  und  ohne  zuviel  Programmieraufwand  geschehen
  3137. kann.  Dennoch  wurde  darauf  geachtet,  daß  dem  Anwender  gegenüber  den
  3138. AES-Fenstern möglichst keine Gestaltungsmöglichkeiten verschlossen wurden.
  3139. Auch die Systemmodule WindowLists und TextWindows bauen auf WindowBase
  3140. auf.
  3141.  
  3142. WindowLists verwaltet Listen in einem Fenster, dies nutzt die  Modula-Shell
  3143. zum Beispiel für ihre Directory-Fenster. Das  Modul  kann  immer  verwendet
  3144. werden,  wenn  eine  Liste  gleichartiger  Daten  zeilenweise  in  einem  Fenster
  3145. dargestellt werden soll, dabei wird jedem Datum eine Zeile zugeordnet.
  3146.  
  3147.  
  3148. Und ganz unten...
  3149.  
  3150. Wollen  Sie  selbst  AES-  oder  VDI-Funktionen  aufrufen,  entweder  weil  Sie
  3151. selbst die Kontrolle haben wollen oder weil eine neue GEM-Funktion in unserer
  3152. GEM-Bibliothek noch nicht zur Verfügung steht, benutzen Sie dazu das Modul
  3153. GEMBase (s. DEMO-Ordner: AESDemo & VDIDemo).
  3154.